Vishnu Mohandas 1 年之前
父節點
當前提交
f73df1f8b7

+ 3 - 0
.gitmodules

@@ -6,3 +6,6 @@
 	path = flutter
 	path = flutter
 	url = https://github.com/flutter/flutter.git
 	url = https://github.com/flutter/flutter.git
 	branch = stable
 	branch = stable
+[submodule "assets/simple-icons"]
+	path = assets/simple-icons
+	url = https://github.com/simple-icons/simple-icons.git

+ 8 - 0
README.md

@@ -101,6 +101,14 @@ For maintainers, there is [additional documentation](RELEASES.md) on
 automatically publishing the main branch to App store, Play store and GitHub
 automatically publishing the main branch to App store, Play store and GitHub
 releases.
 releases.
 
 
+## 🙂 Icons
+
+ente Auth supports the icon pack provided by
+[simple-icons](https://github.com/simple-icons/simple-icons).
+
+If you would like to add your own custom icon, please create a pull-request with
+an SVG for your service that matches the contents within `assets/custom-icons`.
+
 ## 🙋‍♂️ Support
 ## 🙋‍♂️ Support
 
 
 If you need help, please reach out to support@ente.io, and a human will get in
 If you need help, please reach out to support@ente.io, and a human will get in

+ 1 - 0
assets/build/.last_build_id

@@ -0,0 +1 @@
+f23611a675a8c9bc71eb16e8a1108cf8

+ 8 - 0
assets/custom-icons/_data/custom-icons.json

@@ -0,0 +1,8 @@
+{
+    "icons": [
+        {
+            "title": "ente",
+            "hex": "1DB954"
+        }
+    ]
+}

+ 3 - 0
assets/custom-icons/icons/ente.svg

@@ -0,0 +1,3 @@
+<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.06803 7.096C3.33203 7.096 2.68403 6.952 2.12403 6.664C1.57203 6.376 1.14403 5.984 0.840033 5.488C0.536033 4.984 0.384033 4.412 0.384033 3.772C0.384033 3.124 0.532033 2.552 0.828033 2.056C1.13203 1.552 1.54403 1.16 2.06403 0.879997C2.58403 0.591998 3.17203 0.447998 3.82803 0.447998C4.46003 0.447998 5.02803 0.583998 5.53203 0.855998C6.04403 1.12 6.44803 1.504 6.74403 2.008C7.04003 2.504 7.18803 3.1 7.18803 3.796C7.18803 3.868 7.18403 3.952 7.17603 4.048C7.16803 4.136 7.16003 4.22 7.15203 4.3H1.90803V3.208H6.16803L5.44803 3.532C5.44803 3.196 5.38003 2.904 5.24403 2.656C5.10803 2.408 4.92003 2.216 4.68003 2.08C4.44003 1.936 4.16003 1.864 3.84003 1.864C3.52003 1.864 3.23603 1.936 2.98803 2.08C2.74803 2.216 2.56003 2.412 2.42403 2.668C2.28803 2.916 2.22003 3.212 2.22003 3.556V3.844C2.22003 4.196 2.29603 4.508 2.44803 4.78C2.60803 5.044 2.82803 5.248 3.10803 5.392C3.39603 5.528 3.73203 5.596 4.11603 5.596C4.46003 5.596 4.76003 5.544 5.01603 5.44C5.28003 5.336 5.52003 5.18 5.73603 4.972L6.73203 6.052C6.43603 6.388 6.06403 6.648 5.61603 6.832C5.16803 7.008 4.65203 7.096 4.06803 7.096Z" fill="black" style="fill:black;fill:black;fill-opacity:1;"/>
+</svg>

+ 1 - 0
assets/simple-icons

@@ -0,0 +1 @@
+Subproject commit 7e1ad4517598f36ba625741a4dfbc33610d105d8

+ 2 - 0
lib/main.dart

@@ -17,6 +17,7 @@ import 'package:ente_auth/services/user_service.dart';
 import 'package:ente_auth/store/code_store.dart';
 import 'package:ente_auth/store/code_store.dart';
 import 'package:ente_auth/ui/tools/app_lock.dart';
 import 'package:ente_auth/ui/tools/app_lock.dart';
 import 'package:ente_auth/ui/tools/lock_screen.dart';
 import 'package:ente_auth/ui/tools/lock_screen.dart';
+import 'package:ente_auth/ui/utils/icon_utils.dart';
 import 'package:ente_auth/utils/crypto_util.dart';
 import 'package:ente_auth/utils/crypto_util.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/foundation.dart';
 import "package:flutter/material.dart";
 import "package:flutter/material.dart";
@@ -85,4 +86,5 @@ Future<void> _init(bool bool, {String? via}) async {
   await BillingService.instance.init();
   await BillingService.instance.init();
   await NotificationService.instance.init();
   await NotificationService.instance.init();
   await UpdateService.instance.init();
   await UpdateService.instance.init();
+  await IconUtils.instance.init();
 }
 }

+ 27 - 14
lib/ui/code_widget.dart

@@ -8,6 +8,7 @@ import 'package:ente_auth/onboarding/view/setup_enter_secret_key_page.dart';
 import 'package:ente_auth/onboarding/view/view_qr_page.dart';
 import 'package:ente_auth/onboarding/view/view_qr_page.dart';
 import 'package:ente_auth/store/code_store.dart';
 import 'package:ente_auth/store/code_store.dart';
 import 'package:ente_auth/ui/code_timer_progress.dart';
 import 'package:ente_auth/ui/code_timer_progress.dart';
+import 'package:ente_auth/ui/utils/icon_utils.dart';
 import 'package:ente_auth/utils/dialog_util.dart';
 import 'package:ente_auth/utils/dialog_util.dart';
 import 'package:ente_auth/utils/toast_util.dart';
 import 'package:ente_auth/utils/toast_util.dart';
 import 'package:ente_auth/utils/totp_util.dart';
 import 'package:ente_auth/utils/totp_util.dart';
@@ -81,7 +82,7 @@ class _CodeWidgetState extends State<CodeWidget> {
               backgroundColor: Colors.grey.withOpacity(0.1),
               backgroundColor: Colors.grey.withOpacity(0.1),
               borderRadius: const BorderRadius.all(Radius.circular(12.0)),
               borderRadius: const BorderRadius.all(Radius.circular(12.0)),
               foregroundColor:
               foregroundColor:
-              Theme.of(context).colorScheme.inverseBackgroundColor,
+                  Theme.of(context).colorScheme.inverseBackgroundColor,
               icon: Icons.qr_code_2_outlined,
               icon: Icons.qr_code_2_outlined,
               label: "QR",
               label: "QR",
               padding: const EdgeInsets.only(left: 4, right: 0),
               padding: const EdgeInsets.only(left: 4, right: 0),
@@ -90,7 +91,6 @@ class _CodeWidgetState extends State<CodeWidget> {
             const SizedBox(
             const SizedBox(
               width: 4,
               width: 4,
             ),
             ),
-
             SlidableAction(
             SlidableAction(
               onPressed: _onEditPressed,
               onPressed: _onEditPressed,
               backgroundColor: Colors.grey.withOpacity(0.1),
               backgroundColor: Colors.grey.withOpacity(0.1),
@@ -171,14 +171,23 @@ class _CodeWidgetState extends State<CodeWidget> {
                                 ),
                                 ),
                               ],
                               ],
                             ),
                             ),
-                            widget.code.hasSynced != null &&
-                                    widget.code.hasSynced!
-                                ? Container()
-                                : const Icon(
-                                    Icons.sync_disabled,
-                                    size: 20,
-                                    color: Colors.amber,
-                                  ),
+                            Row(
+                              mainAxisAlignment: MainAxisAlignment.end,
+                              children: [
+                                widget.code.hasSynced != null &&
+                                        widget.code.hasSynced!
+                                    ? Container()
+                                    : const Icon(
+                                        Icons.sync_disabled,
+                                        size: 20,
+                                        color: Colors.amber,
+                                      ),
+                                const SizedBox(width: 12),
+                                IconUtils.instance.getIcon(
+                                  safeDecode(widget.code.issuer).trim(),
+                                ),
+                              ],
+                            ),
                           ],
                           ],
                         ),
                         ),
                       ),
                       ),
@@ -231,7 +240,7 @@ class _CodeWidgetState extends State<CodeWidget> {
                                         style:
                                         style:
                                             Theme.of(context).textTheme.caption,
                                             Theme.of(context).textTheme.caption,
                                       ),
                                       ),
-                                       InkWell(
+                                      InkWell(
                                         onTap: _onNextHotpTapped,
                                         onTap: _onNextHotpTapped,
                                         child: const Icon(
                                         child: const Icon(
                                           Icons.forward_outlined,
                                           Icons.forward_outlined,
@@ -264,8 +273,13 @@ class _CodeWidgetState extends State<CodeWidget> {
   }
   }
 
 
   void _onNextHotpTapped() {
   void _onNextHotpTapped() {
-    if(widget.code.type == Type.hotp) {
-     CodeStore.instance.addCode(widget.code.copyWith(counter: widget.code.counter + 1), shouldSync: true).ignore();
+    if (widget.code.type == Type.hotp) {
+      CodeStore.instance
+          .addCode(
+            widget.code.copyWith(counter: widget.code.counter + 1),
+            shouldSync: true,
+          )
+          .ignore();
     }
     }
   }
   }
 
 
@@ -306,7 +320,6 @@ class _CodeWidgetState extends State<CodeWidget> {
     );
     );
   }
   }
 
 
-
   String _getCurrentOTP() {
   String _getCurrentOTP() {
     try {
     try {
       return getOTP(widget.code);
       return getOTP(widget.code);

+ 70 - 0
lib/ui/utils/icon_utils.dart

@@ -0,0 +1,70 @@
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_svg/svg.dart';
+
+class IconUtils {
+  IconUtils._privateConstructor();
+
+  static final IconUtils instance = IconUtils._privateConstructor();
+
+  // Map of icon-title to the color code in HEX
+  final Map<String, String> _simpleIcons = {};
+  final Map<String, String> _customIcons = {};
+
+  Future<void> init() async {
+    await _loadJson();
+  }
+
+  Widget getIcon(String provider) {
+    final title = _getProviderTitle(provider);
+    if (_simpleIcons.containsKey(title)) {
+      return _getSVGIcon(
+        "assets/simple-icons/icons/$title.svg",
+        title,
+        _simpleIcons[title]!,
+      );
+    } else if (_customIcons.containsKey(title)) {
+      return _getSVGIcon(
+        "assets/custom-icons/icons/$title.svg",
+        title,
+        _customIcons[title]!,
+      );
+    } else {
+      return Text(title);
+    }
+  }
+
+  Widget _getSVGIcon(String path, String title, String color) {
+    return SvgPicture.asset(
+      path,
+      width: 24,
+      semanticsLabel: title,
+      colorFilter: ColorFilter.mode(
+        Color(int.parse("0xFF" + color)),
+        BlendMode.srcIn,
+      ),
+    );
+  }
+
+  Future<void> _loadJson() async {
+    final simpleIconData = await rootBundle
+        .loadString('assets/simple-icons/_data/simple-icons.json');
+    final simpleIcons = json.decode(simpleIconData);
+    for (final icon in simpleIcons["icons"]) {
+      _simpleIcons[icon["title"].toString().toLowerCase()] = icon["hex"];
+    }
+    final customIconData = await rootBundle
+        .loadString('assets/custom-icons/_data/custom-icons.json');
+    final customIcons = json.decode(customIconData);
+    for (final icon in customIcons["icons"]) {
+      _customIcons[icon["title"].toString().toLowerCase()] = icon["hex"];
+    }
+  }
+
+  String _getProviderTitle(String provider) {
+    return provider.split(".")[0].toLowerCase();
+  }
+}

+ 32 - 0
pubspec.lock

@@ -589,6 +589,14 @@ packages:
       url: "https://pub.dev"
       url: "https://pub.dev"
     source: hosted
     source: hosted
     version: "6.2.0"
     version: "6.2.0"
+  flutter_svg:
+    dependency: "direct main"
+    description:
+      name: flutter_svg
+      sha256: f991fdb1533c3caeee0cdc14b04f50f0c3916f0dbcbc05237ccbe4e3c6b93f3f
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.5"
   flutter_test:
   flutter_test:
     dependency: "direct dev"
     dependency: "direct dev"
     description: flutter
     description: flutter
@@ -1556,6 +1564,30 @@ packages:
       url: "https://pub.dev"
       url: "https://pub.dev"
     source: hosted
     source: hosted
     version: "3.0.7"
     version: "3.0.7"
+  vector_graphics:
+    dependency: transitive
+    description:
+      name: vector_graphics
+      sha256: ea8d3fc7b2e0f35de38a7465063ecfcf03d8217f7962aa2a6717132cb5d43a79
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.5"
+  vector_graphics_codec:
+    dependency: transitive
+    description:
+      name: vector_graphics_codec
+      sha256: a5eaa5d19e123ad4f61c3718ca1ed921c4e6254238d9145f82aa214955d9aced
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.5"
+  vector_graphics_compiler:
+    dependency: transitive
+    description:
+      name: vector_graphics_compiler
+      sha256: "15edc42f7eaa478ce854eaf1fbb9062a899c0e4e56e775dd73b7f4709c97c4ca"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.5"
   vector_math:
   vector_math:
     dependency: transitive
     dependency: transitive
     description:
     description:

+ 5 - 0
pubspec.yaml

@@ -44,6 +44,7 @@ dependencies:
     git:
     git:
       url: https://github.com/ente-io/flutter_sodium.git
       url: https://github.com/ente-io/flutter_sodium.git
   flutter_speed_dial: ^6.2.0
   flutter_speed_dial: ^6.2.0
+  flutter_svg: ^2.0.5
   fluttertoast: ^8.1.1
   fluttertoast: ^8.1.1
   google_nav_bar: ^5.0.5 #supported
   google_nav_bar: ^5.0.5 #supported
   http: ^0.13.4
   http: ^0.13.4
@@ -92,6 +93,10 @@ flutter:
   # https://docs:flutter:dev/development/ui/assets-and-images:
   # https://docs:flutter:dev/development/ui/assets-and-images:
   assets:
   assets:
     - assets/
     - assets/
+    - assets/simple-icons/icons/
+    - assets/simple-icons/_data/
+    - assets/custom-icons/icons/
+    - assets/custom-icons/_data/
 
 
   fonts:
   fonts:
     - family: Inter
     - family: Inter

二進制
screenshots/screenshots.png