[READ-ONLY] Mirror of https://github.com/probablykasper/notifier. Android app for scheduling notifications
android app flutter notifications
0

Configure Feed

Select the types of activity you want to include in your feed.

Base app

Kasper (May 29, 2022, 9:55 PM +0200) fc7b1246 451b32da

+322 -140
+146
pubspec.lock
··· 57 57 url: "https://pub.dartlang.org" 58 58 source: hosted 59 59 version: "1.3.0" 60 + ffi: 61 + dependency: transitive 62 + description: 63 + name: ffi 64 + url: "https://pub.dartlang.org" 65 + source: hosted 66 + version: "1.2.1" 67 + file: 68 + dependency: transitive 69 + description: 70 + name: file 71 + url: "https://pub.dartlang.org" 72 + source: hosted 73 + version: "6.1.2" 60 74 flutter: 61 75 dependency: "direct main" 62 76 description: flutter ··· 74 88 description: flutter 75 89 source: sdk 76 90 version: "0.0.0" 91 + flutter_web_plugins: 92 + dependency: transitive 93 + description: flutter 94 + source: sdk 95 + version: "0.0.0" 96 + get: 97 + dependency: "direct main" 98 + description: 99 + name: get 100 + url: "https://pub.dartlang.org" 101 + source: hosted 102 + version: "4.6.5" 103 + js: 104 + dependency: transitive 105 + description: 106 + name: js 107 + url: "https://pub.dartlang.org" 108 + source: hosted 109 + version: "0.6.4" 77 110 lints: 78 111 dependency: transitive 79 112 description: ··· 109 142 url: "https://pub.dartlang.org" 110 143 source: hosted 111 144 version: "1.8.1" 145 + path_provider_linux: 146 + dependency: transitive 147 + description: 148 + name: path_provider_linux 149 + url: "https://pub.dartlang.org" 150 + source: hosted 151 + version: "2.1.6" 152 + path_provider_platform_interface: 153 + dependency: transitive 154 + description: 155 + name: path_provider_platform_interface 156 + url: "https://pub.dartlang.org" 157 + source: hosted 158 + version: "2.0.4" 159 + path_provider_windows: 160 + dependency: transitive 161 + description: 162 + name: path_provider_windows 163 + url: "https://pub.dartlang.org" 164 + source: hosted 165 + version: "2.0.6" 166 + platform: 167 + dependency: transitive 168 + description: 169 + name: platform 170 + url: "https://pub.dartlang.org" 171 + source: hosted 172 + version: "3.1.0" 173 + plugin_platform_interface: 174 + dependency: transitive 175 + description: 176 + name: plugin_platform_interface 177 + url: "https://pub.dartlang.org" 178 + source: hosted 179 + version: "2.1.2" 180 + process: 181 + dependency: transitive 182 + description: 183 + name: process 184 + url: "https://pub.dartlang.org" 185 + source: hosted 186 + version: "4.2.4" 187 + shared_preferences: 188 + dependency: "direct main" 189 + description: 190 + name: shared_preferences 191 + url: "https://pub.dartlang.org" 192 + source: hosted 193 + version: "2.0.15" 194 + shared_preferences_android: 195 + dependency: transitive 196 + description: 197 + name: shared_preferences_android 198 + url: "https://pub.dartlang.org" 199 + source: hosted 200 + version: "2.0.12" 201 + shared_preferences_ios: 202 + dependency: transitive 203 + description: 204 + name: shared_preferences_ios 205 + url: "https://pub.dartlang.org" 206 + source: hosted 207 + version: "2.1.1" 208 + shared_preferences_linux: 209 + dependency: transitive 210 + description: 211 + name: shared_preferences_linux 212 + url: "https://pub.dartlang.org" 213 + source: hosted 214 + version: "2.1.1" 215 + shared_preferences_macos: 216 + dependency: transitive 217 + description: 218 + name: shared_preferences_macos 219 + url: "https://pub.dartlang.org" 220 + source: hosted 221 + version: "2.0.4" 222 + shared_preferences_platform_interface: 223 + dependency: transitive 224 + description: 225 + name: shared_preferences_platform_interface 226 + url: "https://pub.dartlang.org" 227 + source: hosted 228 + version: "2.0.0" 229 + shared_preferences_web: 230 + dependency: transitive 231 + description: 232 + name: shared_preferences_web 233 + url: "https://pub.dartlang.org" 234 + source: hosted 235 + version: "2.0.4" 236 + shared_preferences_windows: 237 + dependency: transitive 238 + description: 239 + name: shared_preferences_windows 240 + url: "https://pub.dartlang.org" 241 + source: hosted 242 + version: "2.1.1" 112 243 sky_engine: 113 244 dependency: transitive 114 245 description: flutter ··· 163 294 url: "https://pub.dartlang.org" 164 295 source: hosted 165 296 version: "2.1.2" 297 + win32: 298 + dependency: transitive 299 + description: 300 + name: win32 301 + url: "https://pub.dartlang.org" 302 + source: hosted 303 + version: "2.6.1" 304 + xdg_directories: 305 + dependency: transitive 306 + description: 307 + name: xdg_directories 308 + url: "https://pub.dartlang.org" 309 + source: hosted 310 + version: "0.2.0+1" 166 311 sdks: 167 312 dart: ">=2.17.1 <3.0.0" 313 + flutter: ">=2.8.0"
+2
pubspec.yaml
··· 34 34 # The following adds the Cupertino Icons font to your application. 35 35 # Use with the CupertinoIcons class for iOS style icons. 36 36 cupertino_icons: ^1.0.2 37 + shared_preferences: ^2.0.15 38 + get: ^4.6.5 37 39 38 40 dev_dependencies: 39 41 flutter_test:
+64
lib/list_page.dart
··· 1 + import 'package:get/get.dart' 2 + show Get, GetNavigation, GetxController, Inst, Obx, RxInt; 3 + import 'package:flutter/material.dart' 4 + show 5 + AlertDialog, 6 + AppBar, 7 + BuildContext, 8 + Center, 9 + ElevatedButton, 10 + FloatingActionButton, 11 + Icon, 12 + Icons, 13 + Scaffold, 14 + StatelessWidget, 15 + Text, 16 + ThemeData, 17 + Widget, 18 + showDialog; 19 + 20 + class Controller extends GetxController { 21 + var count = RxInt(0); 22 + increment() => count++; 23 + } 24 + 25 + class ListPage extends StatelessWidget { 26 + @override 27 + Widget build(context) { 28 + // Instantiate your class using Get.put() to make it available for all "child" routes there. 29 + final Controller c = Get.put(Controller()); 30 + 31 + return Scaffold( 32 + // Use Obx(()=> to update Text() whenever count is changed. 33 + appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))), 34 + 35 + // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context 36 + body: Center( 37 + child: ElevatedButton( 38 + child: const Text("Go to Other"), 39 + onPressed: () => Get.to(() => Other()))), 40 + floatingActionButton: FloatingActionButton( 41 + child: const Icon(Icons.add), 42 + onPressed: () { 43 + var title = Get.isDarkMode ? "Was dark" : "Wasn't dark"; 44 + showDialog( 45 + context: context, 46 + builder: (BuildContext context) => AlertDialog( 47 + title: Text(title), 48 + )); 49 + Get.changeTheme( 50 + Get.isDarkMode ? ThemeData.light() : ThemeData.dark()); 51 + })); 52 + } 53 + } 54 + 55 + class Other extends StatelessWidget { 56 + // You can ask Get to find a Controller that is being used by another page and redirect you to it. 57 + final Controller c = Get.find(); 58 + 59 + @override 60 + Widget build(context) { 61 + // Access the updated count variable 62 + return Scaffold(body: Center(child: Text("${c.count}"))); 63 + } 64 + }
+32 -110
lib/main.dart
··· 1 - import 'package:flutter/material.dart'; 1 + import 'package:flutter/material.dart' 2 + show ThemeData, ThemeMode, WidgetsFlutterBinding, runApp; 3 + import 'theme.dart' show getTheme; 4 + import 'list_page.dart' show ListPage; 5 + import 'package:shared_preferences/shared_preferences.dart' 6 + show SharedPreferences; 7 + import 'package:get/get.dart' show Get, GetMaterialApp, GetNavigation; 2 8 3 - void main() { 4 - runApp(const MyApp()); 9 + var prefsFuture = SharedPreferences.getInstance(); 10 + 11 + void main() async { 12 + // WidgetsFlutterBinding.ensureInitialized(); 13 + // var prefs = prefsFuture.then((prefs) { 14 + 15 + // }) 16 + // var darkMode = prefs.getBool('darkMode') ?? true; 17 + runApp( 18 + GetMaterialApp( 19 + title: 'Notifier', 20 + // debugShowCheckedModeBanner: false, 21 + theme: getTheme(false), 22 + darkTheme: getTheme(true), 23 + themeMode: ThemeMode.system, 24 + home: ListPage()), 25 + ); 26 + setupDarkMode(); 5 27 } 6 28 7 - class MyApp extends StatelessWidget { 8 - const MyApp({Key? key}) : super(key: key); 9 - 10 - // This widget is the root of your application. 11 - @override 12 - Widget build(BuildContext context) { 13 - return MaterialApp( 14 - title: 'Flutter Demo', 15 - theme: ThemeData( 16 - // This is the theme of your application. 17 - // 18 - // Try running your application with "flutter run". You'll see the 19 - // application has a blue toolbar. Then, without quitting the app, try 20 - // changing the primarySwatch below to Colors.green and then invoke 21 - // "hot reload" (press "r" in the console where you ran "flutter run", 22 - // or simply save your changes to "hot reload" in a Flutter IDE). 23 - // Notice that the counter didn't reset back to zero; the application 24 - // is not restarted. 25 - primarySwatch: Colors.blue, 26 - ), 27 - home: const MyHomePage(title: 'Flutter Demo Home Page'), 28 - ); 29 - } 30 - } 31 - 32 - class MyHomePage extends StatefulWidget { 33 - const MyHomePage({Key? key, required this.title}) : super(key: key); 34 - 35 - // This widget is the home page of your application. It is stateful, meaning 36 - // that it has a State object (defined below) that contains fields that affect 37 - // how it looks. 38 - 39 - // This class is the configuration for the state. It holds the values (in this 40 - // case the title) provided by the parent (in this case the App widget) and 41 - // used by the build method of the State. Fields in a Widget subclass are 42 - // always marked "final". 43 - 44 - final String title; 45 - 46 - @override 47 - State<MyHomePage> createState() => _MyHomePageState(); 48 - } 49 - 50 - class _MyHomePageState extends State<MyHomePage> { 51 - int _counter = 0; 52 - 53 - void _incrementCounter() { 54 - setState(() { 55 - // This call to setState tells the Flutter framework that something has 56 - // changed in this State, which causes it to rerun the build method below 57 - // so that the display can reflect the updated values. If we changed 58 - // _counter without calling setState(), then the build method would not be 59 - // called again, and so nothing would appear to happen. 60 - _counter++; 61 - }); 62 - } 63 - 64 - @override 65 - Widget build(BuildContext context) { 66 - // This method is rerun every time setState is called, for instance as done 67 - // by the _incrementCounter method above. 68 - // 69 - // The Flutter framework has been optimized to make rerunning build methods 70 - // fast, so that you can just rebuild anything that needs updating rather 71 - // than having to individually change instances of widgets. 72 - return Scaffold( 73 - appBar: AppBar( 74 - // Here we take the value from the MyHomePage object that was created by 75 - // the App.build method, and use it to set our appbar title. 76 - title: Text(widget.title), 77 - ), 78 - body: Center( 79 - // Center is a layout widget. It takes a single child and positions it 80 - // in the middle of the parent. 81 - child: Column( 82 - // Column is also a layout widget. It takes a list of children and 83 - // arranges them vertically. By default, it sizes itself to fit its 84 - // children horizontally, and tries to be as tall as its parent. 85 - // 86 - // Invoke "debug painting" (press "p" in the console, choose the 87 - // "Toggle Debug Paint" action from the Flutter Inspector in Android 88 - // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) 89 - // to see the wireframe for each widget. 90 - // 91 - // Column has various properties to control how it sizes itself and 92 - // how it positions its children. Here we use mainAxisAlignment to 93 - // center the children vertically; the main axis here is the vertical 94 - // axis because Columns are vertical (the cross axis would be 95 - // horizontal). 96 - mainAxisAlignment: MainAxisAlignment.center, 97 - children: <Widget>[ 98 - const Text( 99 - 'You have pushed the button this many times:', 100 - ), 101 - Text( 102 - '$_counter', 103 - style: Theme.of(context).textTheme.headline4, 104 - ), 105 - ], 106 - ), 107 - ), 108 - floatingActionButton: FloatingActionButton( 109 - onPressed: _incrementCounter, 110 - tooltip: 'Increment', 111 - child: const Icon(Icons.add), 112 - ), // This trailing comma makes auto-formatting nicer for build methods. 113 - ); 29 + void setupDarkMode() async { 30 + var prefs = await prefsFuture; 31 + var darkMode = prefs.getBool("darkMode"); 32 + if (darkMode == true) { 33 + Get.changeTheme(getTheme(true)); 34 + } else { 35 + Get.changeTheme(getTheme(false)); 114 36 } 115 37 }
+78
lib/theme.dart
··· 1 + import 'package:flutter/material.dart' 2 + show 3 + BorderRadius, 4 + Brightness, 5 + ButtonThemeData, 6 + CardTheme, 7 + Color, 8 + Colors, 9 + DialogTheme, 10 + FloatingActionButtonThemeData, 11 + RoundedRectangleBorder, 12 + ThemeData; 13 + 14 + ThemeData getTheme(bool darkMode) { 15 + var grey = { 16 + 1: const Color(0xFF121212), 17 + 2: const Color(0xFF202124), 18 + 3: const Color(0xFF313234), 19 + 4: const Color(0xFF43454c), 20 + 5: const Color(0xFF54565f), 21 + 6: const Color(0xFF676974), 22 + 7: Colors.grey.shade500, 23 + 8: Colors.grey.shade400, 24 + 9: Colors.grey.shade100, 25 + }; 26 + var white = { 27 + 1: Colors.grey.shade100, 28 + 2: Colors.grey.shade200, 29 + 3: Colors.grey.shade300, 30 + 4: Colors.grey.shade400, 31 + 5: Colors.grey.shade500, 32 + 6: Colors.grey.shade600, 33 + 7: Colors.grey.shade700, 34 + 8: Colors.grey.shade800, 35 + 9: Colors.grey.shade900, 36 + }; 37 + const blue = Color(0xFF00B0FF); 38 + var color = darkMode ? grey : white; 39 + 40 + var backgroundColor = color[1]; 41 + var splashColor = color[6]?.withOpacity(0.3); 42 + 43 + return ThemeData( 44 + fontFamily: 'Jost', 45 + brightness: darkMode ? Brightness.dark : Brightness.light, 46 + scaffoldBackgroundColor: backgroundColor, 47 + // textSelectionColor: Colors.white24, 48 + // textSelectionHandleColor: blue, 49 + // accentColor: Colors.white, 50 + toggleableActiveColor: blue, 51 + floatingActionButtonTheme: FloatingActionButtonThemeData( 52 + foregroundColor: Colors.white, 53 + backgroundColor: darkMode ? color[3] : blue, 54 + ), 55 + // buttonColor: Colors.yellowAccent, 56 + highlightColor: 57 + darkMode ? color[6]?.withOpacity(0.3) : color[6]?.withOpacity(0.2), 58 + splashColor: splashColor, 59 + buttonTheme: ButtonThemeData( 60 + minWidth: 85, 61 + height: 35, 62 + shape: RoundedRectangleBorder( 63 + borderRadius: BorderRadius.circular(4), 64 + ), 65 + ), 66 + cardTheme: CardTheme( 67 + shape: RoundedRectangleBorder( 68 + borderRadius: BorderRadius.circular(4), 69 + ), 70 + ), 71 + dialogTheme: DialogTheme( 72 + backgroundColor: darkMode ? color[2] : Colors.white, 73 + shape: RoundedRectangleBorder( 74 + borderRadius: BorderRadius.circular(4), 75 + ), 76 + ), 77 + ); 78 + }
-30
test/widget_test.dart
··· 1 - // This is a basic Flutter widget test. 2 - // 3 - // To perform an interaction with a widget in your test, use the WidgetTester 4 - // utility in the flutter_test package. For example, you can send tap and scroll 5 - // gestures. You can also use WidgetTester to find child widgets in the widget 6 - // tree, read text, and verify that the values of widget properties are correct. 7 - 8 - import 'package:flutter/material.dart'; 9 - import 'package:flutter_test/flutter_test.dart'; 10 - 11 - import 'package:notifier/main.dart'; 12 - 13 - void main() { 14 - testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 - // Build our app and trigger a frame. 16 - await tester.pumpWidget(const MyApp()); 17 - 18 - // Verify that our counter starts at 0. 19 - expect(find.text('0'), findsOneWidget); 20 - expect(find.text('1'), findsNothing); 21 - 22 - // Tap the '+' icon and trigger a frame. 23 - await tester.tap(find.byIcon(Icons.add)); 24 - await tester.pump(); 25 - 26 - // Verify that our counter has incremented. 27 - expect(find.text('0'), findsNothing); 28 - expect(find.text('1'), findsOneWidget); 29 - }); 30 - }