Skip to content

Commit

Permalink
テーマをインストールできるように
Browse files Browse the repository at this point in the history
  • Loading branch information
poppingmoon committed Jan 28, 2024
1 parent 07e6895 commit 26975cc
Show file tree
Hide file tree
Showing 11 changed files with 757 additions and 343 deletions.
11 changes: 11 additions & 0 deletions lib/l10n/app_ja.arb
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,10 @@
}
}
},

"invalidThemeFormat": "テーマの形式が間違っています",
"duplicatedTheme": "このテーマは既にインストールされています",

"importFromThisFolder": "このフォルダーからインポートする",
"exportedFileNotFound": "ここにMiriaの設定ファイルあれへんかったわ",
"importCompleted": "インポート終わったで。",
Expand Down Expand Up @@ -795,6 +799,7 @@
}
},
"selectLightOrDarkMode": "ライトモード・ダークモードのつかいわけ",
"manageThemes": "テーマの管理",
"reaction": "リアクション",
"emojiTapReaction": "ノート内の絵文字タップでリアクションする",
"emojiTapReactionDescription": "ノート内の絵文字をタップしてリアクションします。MFMや外部サーバーの絵文字の場合うまく機能しないことがあります。",
Expand All @@ -806,6 +811,12 @@
"fontFantasy": "フォント ($[font.fantasy 用)",
"fontSize": "フォントサイズ",
"systemFont": "システム標準",
"installTheme": "テーマのインストール",
"themeCode": "テーマコード",
"install": "インストール",
"installedThemes": "インストールされたテーマ",
"noInstalledThemes": "インストールされたテーマがありません",
"confirmDeleteTheme": "このテーマを削除しますか?",

"selectFolder": "フォルダー選択",
"importSettings": "設定のインポート",
Expand Down
12 changes: 12 additions & 0 deletions lib/providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:file/local.dart';
import 'package:flutter/widgets.dart';
import 'package:miria/model/account.dart';
import 'package:miria/model/acct.dart';
import 'package:miria/model/color_theme.dart';
import 'package:miria/model/tab_setting.dart';
import 'package:miria/repository/account_repository.dart';
import 'package:miria/repository/account_settings_repository.dart';
Expand All @@ -14,6 +15,7 @@ import 'package:miria/repository/favorite_repository.dart';
import 'package:miria/repository/general_settings_repository.dart';
import 'package:miria/repository/hybrid_timeline_repository.dart';
import 'package:miria/repository/import_export_repository.dart';
import 'package:miria/repository/color_theme_repository.dart';
import 'package:miria/repository/main_stream_repository.dart';
import 'package:miria/repository/global_time_line_repository.dart';
import 'package:miria/repository/home_time_line_repository.dart';
Expand Down Expand Up @@ -299,3 +301,13 @@ final antennasNotifierProvider = AsyncNotifierProvider.autoDispose

final clipsNotifierProvider = AsyncNotifierProvider.autoDispose
.family<ClipsNotifier, List<Clip>, Misskey>(ClipsNotifier.new);

final colorThemeRepositoryProvider =
NotifierProvider<ColorThemeRepository, List<ColorTheme>>(
ColorThemeRepository.new,
);

final installedThemeCodeRepositoryProvider =
NotifierProvider<InstalledThemeCodeRepository, List<String>>(
InstalledThemeCodeRepository.new,
);
93 changes: 93 additions & 0 deletions lib/repository/color_theme_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:json5/json5.dart';
import 'package:miria/model/color_theme.dart';
import 'package:miria/model/misskey_theme.dart';
import 'package:miria/providers.dart';
import 'package:miria/view/themes/built_in_color_themes.dart';
import 'package:shared_preferences/shared_preferences.dart';

sealed class ColorThemeException implements Exception {}

class InvalidThemeFormatException implements ColorThemeException {}

class DuplicatedThemeException implements ColorThemeException {}

class ColorThemeRepository extends Notifier<List<ColorTheme>> {
@override
List<ColorTheme> build() {
final codes = ref.watch(installedThemeCodeRepositoryProvider);
return [
...builtInColorThemes,
...codes.map((code) {
try {
return ColorTheme.misskey(
MisskeyTheme.fromJson(json5Decode(code) as Map<String, dynamic>),
);
} catch (e) {
return null;
}
}).nonNulls,
];
}

Future<void> addTheme(String code) async {
final ColorTheme theme;
try {
theme = ColorTheme.misskey(
MisskeyTheme.fromJson(json5Decode(code) as Map<String, dynamic>),
);
} catch (e) {
throw InvalidThemeFormatException();
}
if (state.any((element) => element.id == theme.id)) {
throw DuplicatedThemeException();
}

await ref
.read(installedThemeCodeRepositoryProvider.notifier)
.addTheme(code);
}

Future<void> removeTheme(String id) async {
await ref
.read(installedThemeCodeRepositoryProvider.notifier)
.removeTheme(id);
}
}

class InstalledThemeCodeRepository extends Notifier<List<String>> {
final prefsKey = "themes";

@override
List<String> build() {
Future(load);
return [];
}

Future<void> load() async {
final prefs = await SharedPreferences.getInstance();
final themes = prefs.getStringList(prefsKey);
if (themes == null) {
return;
}
state = themes;
}

Future<void> addTheme(String code) async {
final prefs = await SharedPreferences.getInstance();
final codes = prefs.getStringList(prefsKey) ?? [];
codes.add(code);
await prefs.setStringList(prefsKey, codes);
state = codes;
}

Future<void> removeTheme(String id) async {
final prefs = await SharedPreferences.getInstance();
final codes = prefs.getStringList(prefsKey);
codes!.removeWhere(
(code) => (json5Decode(code) as Map<String, dynamic>)["id"] == id,
);
await prefs.setStringList(prefsKey, codes);
state = codes;
}
}
2 changes: 2 additions & 0 deletions lib/router/app_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import 'package:miria/view/photo_edit_page/photo_edit_page.dart';
import 'package:miria/view/settings_page/account_settings_page/account_list.dart';
import 'package:miria/view/settings_page/app_info_page/app_info_page.dart';
import 'package:miria/view/settings_page/general_settings_page/general_settings_page.dart';
import 'package:miria/view/settings_page/general_settings_page/installed_themes_page.dart';
import 'package:miria/view/settings_page/import_export_page/import_export_page.dart';
import 'package:miria/view/settings_page/tab_settings_page/tab_settings_list_page.dart';
import 'package:miria/view/several_account_settings_page/cache_management_page/cache_management_page.dart';
Expand Down Expand Up @@ -102,5 +103,6 @@ class AppRouter extends _$AppRouter {
AutoRoute(page: MisskeyGamesRoute.page),
// きしょ……
AutoRoute(page: MisskeyRouteRoute.page),
AutoRoute(page: InstalledThemesRoute.page),
];
}
116 changes: 68 additions & 48 deletions lib/router/app_router.gr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions lib/view/common/error_dialog_listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:miria/providers.dart';
import 'package:miria/repository/account_repository.dart';
import 'package:miria/repository/color_theme_repository.dart';
import 'package:miria/state_notifier/common/misskey_notes/misskey_note_notifier.dart';
import 'package:miria/state_notifier/note_create_page/note_create_state_notifier.dart';
import 'package:miria/view/common/error_dialog_handler.dart';
Expand Down Expand Up @@ -56,11 +57,19 @@ class ErrorDialogListener extends ConsumerWidget {
S.of(context).cannotMentionToRemoteInLocalOnlyNote,
};
SimpleMessageDialog.show(next.$2!, message);
} else if (error is ColorThemeException) {
final message = switch (error) {
InvalidThemeFormatException() => S.of(context).invalidThemeFormat,
DuplicatedThemeException() => S.of(context).duplicatedTheme,
};
SimpleMessageDialog.show(next.$2!, message);
} else {
SimpleMessageDialog.show(next.$2!, "${S.of(context).thrownError}\n$next");
SimpleMessageDialog.show(
next.$2!, "${S.of(context).thrownError}\n$next");
}
} else if (error is Error) {
SimpleMessageDialog.show(next.$2!, "${S.of(context).thrownError}\n$next");
SimpleMessageDialog.show(
next.$2!, "${S.of(context).thrownError}\n$next");
}
});

Expand Down
Loading

0 comments on commit 26975cc

Please sign in to comment.