Skip to content

Instantly share code, notes, and snippets.

@deminearchiver
Last active January 21, 2026 15:42
Show Gist options
  • Select an option

  • Save deminearchiver/aa89bd948d0bfdf617cdaed23119b28a to your computer and use it in GitHub Desktop.

Select an option

Save deminearchiver/aa89bd948d0bfdf617cdaed23119b28a to your computer and use it in GitHub Desktop.
Design suggsetion for ImranR98/Obtainium#2742.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.amber,
dynamicSchemeVariant: .fidelity,
brightness: .dark,
),
platform: .android,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({super.key, required this.title});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Widget buildRepoRenameWarning({
required AppInMemory? app,
required AppsProvider appsProvider,
required Future<void> Function(String id) onUpdate,
}) {
if (app?.app.hasPendingRepoRename != true) {
return const SizedBox.shrink();
}
var appValue = app!;
var pendingUrl = appValue.app.pendingRepoRenameUrl!;
final colorScheme = ColorScheme.of(context);
final textTheme = TextTheme.of(context);
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
spacing: 2,
children: [
Material(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(16),
bottom: Radius.circular(4),
),
),
color: colorScheme.surfaceContainer,
child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: 48),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Row(
spacing: 12,
children: [
Icon(
Icons.info_outline_rounded,
size: 24,
color: colorScheme.onSurfaceVariant,
),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
tr('repoRenamed'),
style: textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color: colorScheme.onSurface,
),
),
Text(
tr('repoRenamedExplanation'),
style: textTheme.bodyMedium?.copyWith(
color: colorScheme.onSurfaceVariant,
),
),
],
),
),
],
),
),
),
),
Material(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
),
color: colorScheme.surfaceContainer,
child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: 48),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Row(
spacing: 12,
children: [
Icon(
Icons.link_rounded,
size: 24,
color: colorScheme.onSurfaceVariant,
),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
tr('newUrl'),
style: textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color: colorScheme.onSurface,
),
),
Text(
pendingUrl,
style: textTheme.bodyMedium?.copyWith(
color: colorScheme.onSurfaceVariant,
),
),
],
),
),
],
),
),
),
),
Material(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(4),
bottom: Radius.circular(16),
),
),
color: colorScheme.surfaceContainer,
child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: 48),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
// Min tap target has a height of 48dp
vertical: 10 - 4,
),
child: Row(
spacing: 12,
children: [
Expanded(
child: OutlinedButton(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.fromMap({
WidgetState.disabled: colorScheme.onSurface
.withValues(alpha: 0.10),
WidgetState.any: Colors.transparent,
}),
side: WidgetStatePropertyAll(
BorderSide(
width: 1,
strokeAlign: BorderSide.strokeAlignInside,
color: colorScheme.outlineVariant,
),
),
elevation: WidgetStatePropertyAll(0),
overlayColor: WidgetStateProperty.fromMap({
WidgetState.disabled: colorScheme.onSurfaceVariant
.withAlpha(0),
WidgetState.pressed: colorScheme.onSurfaceVariant
.withValues(alpha: 0.10),
WidgetState.focused: colorScheme.onSurfaceVariant
.withValues(alpha: 0.10),
WidgetState.hovered: colorScheme.onSurfaceVariant
.withValues(alpha: 0.08),
WidgetState.any: colorScheme.onSurfaceVariant
.withAlpha(0),
}),
foregroundColor: WidgetStateProperty.fromMap({
WidgetState.disabled: colorScheme.onSurface
.withValues(alpha: 0.38),
WidgetState.any: colorScheme.onSurfaceVariant,
}),
textStyle: WidgetStatePropertyAll(textTheme.labelLarge),
),
onPressed: () async {
await appsProvider.updatePendingRepoRename(
appValue.app.id,
null,
);
},
child: Text(tr('dismiss')),
),
),
Expanded(
child: FilledButton.tonal(
style: ButtonStyle(
elevation: WidgetStatePropertyAll(0),
textStyle: WidgetStatePropertyAll(
textTheme.labelLarge?.copyWith(
fontWeight: FontWeight.w600,
),
),
),
onPressed: () async {
await appsProvider.acceptRepoRename(
appValue.app.id,
pendingUrl,
);
if (mounted) {
onUpdate(appValue.app.id);
}
},
child: Text(tr('updateUrl')),
),
),
],
),
),
),
),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: buildRepoRenameWarning(
app: AppInMemory(),
appsProvider: AppsProvider(),
onUpdate: (String _) async {},
),
),
);
}
}
class App {
String get id => "app.id";
bool? get hasPendingRepoRename => true;
String? get pendingRepoRenameUrl => "https://github.com/foo/bar";
}
class AppInMemory {
App get app => App();
}
class AppsProvider {
Future<void> acceptRepoRename(String _, String _) async {}
Future<void> updatePendingRepoRename(String _, String? _) async {}
}
String tr(String key) {
return "tr($key)";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment