mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-05-16 13:12:40 +00:00
Merge pull request #526 from Schnitzel5/feature/discord-rpc
added discord rpc
This commit is contained in:
commit
204c4f698c
33 changed files with 1500 additions and 354 deletions
18
.github/workflows/release.yml
vendored
18
.github/workflows/release.yml
vendored
|
|
@ -52,7 +52,7 @@ jobs:
|
|||
uses: seanmiddleditch/gha-setup-ninja@master
|
||||
|
||||
- name: Install the CLI tool
|
||||
run: cargo install 'flutter_rust_bridge_codegen' --locked
|
||||
run: cargo install 'flutter_rust_bridge_codegen'
|
||||
|
||||
- name: Setup Android keystore
|
||||
run: |
|
||||
|
|
@ -105,7 +105,7 @@ jobs:
|
|||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install the CLI tool
|
||||
run: cargo install 'flutter_rust_bridge_codegen' --locked
|
||||
run: cargo install 'flutter_rust_bridge_codegen'
|
||||
|
||||
- name: flutter pub get
|
||||
run: flutter pub get
|
||||
|
|
@ -125,7 +125,7 @@ jobs:
|
|||
env:
|
||||
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
|
||||
run: |
|
||||
flutter build ios --release --no-codesign
|
||||
flutter build ios --release --no-codesign --verbose
|
||||
mkdir -p build/ios/iphoneos/Payload
|
||||
ln -s ../Runner.app build/ios/iphoneos/Payload/Runner.app
|
||||
./zsign -f -k ./certificate.p12 -p "$P12_PASSWORD" -m ./profile.mobileprovision ./build/ios/iphoneos/Payload/Runner.app
|
||||
|
|
@ -161,7 +161,7 @@ jobs:
|
|||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install the CLI tool
|
||||
run: cargo install 'flutter_rust_bridge_codegen' --locked
|
||||
run: cargo install 'flutter_rust_bridge_codegen'
|
||||
|
||||
- name: flutter pub get
|
||||
run: flutter pub get
|
||||
|
|
@ -171,7 +171,7 @@ jobs:
|
|||
cd macos
|
||||
pod update
|
||||
cd ..
|
||||
flutter build macos --release
|
||||
flutter build macos --release --verbose
|
||||
brew install create-dmg
|
||||
create-dmg --volname Mangayomi-${{ github.ref_name }}-macos --window-pos 200 120 --window-size 800 450 --icon-size 100 --app-drop-link 600 185 Mangayomi-${{ github.ref_name }}-macos.dmg build/macos/Build/Products/Release/Mangayomi.app
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ jobs:
|
|||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install the CLI tool
|
||||
run: cargo install 'flutter_rust_bridge_codegen' --locked
|
||||
run: cargo install 'flutter_rust_bridge_codegen'
|
||||
|
||||
- name: flutter pub get
|
||||
run: flutter pub get
|
||||
|
|
@ -271,13 +271,13 @@ jobs:
|
|||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install the CLI tool
|
||||
run: cargo install 'flutter_rust_bridge_codegen' --locked
|
||||
run: cargo install 'flutter_rust_bridge_codegen'
|
||||
|
||||
- name: flutter pub get
|
||||
run: flutter pub get
|
||||
|
||||
- name: build linux
|
||||
run: flutter build linux --release
|
||||
run: flutter build linux --release --verbose
|
||||
|
||||
- name: Zip
|
||||
uses: thedoctor0/zip-release@master
|
||||
|
|
@ -402,7 +402,7 @@ jobs:
|
|||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install the CLI tool
|
||||
run: cargo install 'flutter_rust_bridge_codegen' --locked
|
||||
run: cargo install 'flutter_rust_bridge_codegen'
|
||||
|
||||
- name: flutter pub get
|
||||
run: flutter pub get
|
||||
|
|
|
|||
|
|
@ -463,5 +463,10 @@
|
|||
"track_library_not_logged": "Login to the corresponding tracker to use this feature!",
|
||||
"track_library_switch": "Switch to another tracker",
|
||||
"go_back": "Go back",
|
||||
"merge_library_nav_mobile": "Merge library navigation on mobile"
|
||||
}
|
||||
"merge_library_nav_mobile": "Merge library navigation on mobile",
|
||||
"enable_discord_rpc": "Enable Discord RPC",
|
||||
"hide_discord_rpc_incognito": "Hide Discord RPC while in Incognito",
|
||||
"rpc_show_reading_watching_progress": "Show current chapter in Discord (requires a restart)",
|
||||
"rpc_show_title": "Show current title in Discord",
|
||||
"rpc_show_cover_image": "Show current cover image in Discord"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2854,6 +2854,36 @@ abstract class AppLocalizations {
|
|||
/// In en, this message translates to:
|
||||
/// **'Merge library navigation on mobile'**
|
||||
String get merge_library_nav_mobile;
|
||||
|
||||
/// No description provided for @enable_discord_rpc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enable Discord RPC'**
|
||||
String get enable_discord_rpc;
|
||||
|
||||
/// No description provided for @hide_discord_rpc_incognito.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Hide Discord RPC while in Incognito'**
|
||||
String get hide_discord_rpc_incognito;
|
||||
|
||||
/// No description provided for @rpc_show_reading_watching_progress.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Show current chapter in Discord (requires a restart)'**
|
||||
String get rpc_show_reading_watching_progress;
|
||||
|
||||
/// No description provided for @rpc_show_title.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Show current title in Discord'**
|
||||
String get rpc_show_title;
|
||||
|
||||
/// No description provided for @rpc_show_cover_image.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Show current cover image in Discord'**
|
||||
String get rpc_show_cover_image;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
|
|
|||
|
|
@ -1468,4 +1468,21 @@ class AppLocalizationsAr extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1481,4 +1481,21 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1469,4 +1469,21 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1486,6 +1486,23 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
||||
/// The translations for Spanish Castilian, as used in Latin America and the Caribbean (`es_419`).
|
||||
|
|
|
|||
|
|
@ -1487,4 +1487,21 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1475,4 +1475,21 @@ class AppLocalizationsId extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1484,4 +1484,21 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1483,6 +1483,23 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
||||
/// The translations for Portuguese, as used in Brazil (`pt_BR`).
|
||||
|
|
|
|||
|
|
@ -1485,4 +1485,21 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1469,4 +1469,21 @@ class AppLocalizationsTh extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1475,4 +1475,21 @@ class AppLocalizationsTr extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1440,4 +1440,21 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get merge_library_nav_mobile => 'Merge library navigation on mobile';
|
||||
|
||||
@override
|
||||
String get enable_discord_rpc => 'Enable Discord RPC';
|
||||
|
||||
@override
|
||||
String get hide_discord_rpc_incognito =>
|
||||
'Hide Discord RPC while in Incognito';
|
||||
|
||||
@override
|
||||
String get rpc_show_reading_watching_progress =>
|
||||
'Show current chapter in Discord (requires a restart)';
|
||||
|
||||
@override
|
||||
String get rpc_show_title => 'Show current title in Discord';
|
||||
|
||||
@override
|
||||
String get rpc_show_cover_image => 'Show current cover image in Discord';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import 'package:mangayomi/modules/more/settings/appearance/providers/theme_mode_
|
|||
import 'package:mangayomi/l10n/generated/app_localizations.dart';
|
||||
import 'package:mangayomi/services/http/m_client.dart';
|
||||
import 'package:mangayomi/src/rust/frb_generated.dart';
|
||||
import 'package:mangayomi/utils/discord_rpc.dart';
|
||||
import 'package:mangayomi/utils/url_protocol/api.dart';
|
||||
import 'package:mangayomi/modules/more/settings/appearance/providers/theme_provider.dart';
|
||||
import 'package:mangayomi/modules/library/providers/file_scanner.dart';
|
||||
|
|
@ -35,6 +36,7 @@ import 'package:window_manager/window_manager.dart';
|
|||
import 'package:path/path.dart' as p;
|
||||
|
||||
late Isar isar;
|
||||
late DiscordRPC discordRpc;
|
||||
WebViewEnvironment? webViewEnvironment;
|
||||
void main(List<String> args) async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
|
@ -61,6 +63,8 @@ void main(List<String> args) async {
|
|||
isar = await StorageProvider().initDB(null, inspector: kDebugMode);
|
||||
await Hive.initFlutter();
|
||||
Hive.registerAdapter(TrackSearchAdapter());
|
||||
discordRpc = DiscordRPC(applicationId: "1395040506677039157");
|
||||
await discordRpc.initialize();
|
||||
|
||||
runApp(const ProviderScope(child: MyApp()));
|
||||
unawaited(_postLaunchInit()); // Defer non-essential async operations
|
||||
|
|
@ -129,6 +133,7 @@ class _MyAppState extends ConsumerState<MyApp> {
|
|||
@override
|
||||
void dispose() {
|
||||
_linkSubscription?.cancel();
|
||||
discordRpc.destroy();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -246,6 +246,16 @@ class Settings {
|
|||
|
||||
bool? mergeLibraryNavMobile;
|
||||
|
||||
bool? enableDiscordRpc;
|
||||
|
||||
bool? hideDiscordRpcInIncognito;
|
||||
|
||||
bool? rpcShowReadingWatchingProgress;
|
||||
|
||||
bool? rpcShowTitle;
|
||||
|
||||
bool? rpcShowCoverImage;
|
||||
|
||||
Settings({
|
||||
this.id = 227,
|
||||
this.displayType = DisplayType.compactGrid,
|
||||
|
|
@ -355,6 +365,11 @@ class Settings {
|
|||
this.novelExtensionsRepo,
|
||||
this.lastTrackerLibraryLocation,
|
||||
this.mergeLibraryNavMobile = false,
|
||||
this.enableDiscordRpc = true,
|
||||
this.hideDiscordRpcInIncognito = true,
|
||||
this.rpcShowReadingWatchingProgress = true,
|
||||
this.rpcShowTitle = true,
|
||||
this.rpcShowCoverImage = true,
|
||||
});
|
||||
|
||||
Settings.fromJson(Map<String, dynamic> json) {
|
||||
|
|
@ -570,6 +585,11 @@ class Settings {
|
|||
}
|
||||
lastTrackerLibraryLocation = json['lastTrackerLibraryLocation'];
|
||||
mergeLibraryNavMobile = json['mergeLibraryNavMobile'];
|
||||
enableDiscordRpc = json['enableDiscordRpc'];
|
||||
hideDiscordRpcInIncognito = json['hideDiscordRpcInIncognito'];
|
||||
rpcShowReadingWatchingProgress = json['rpcShowReadingWatchingProgress'];
|
||||
rpcShowTitle = json['rpcShowTitle'];
|
||||
rpcShowCoverImage = json['rpcShowCoverImage'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
|
@ -702,6 +722,11 @@ class Settings {
|
|||
'novelExtensionsRepo': novelExtensionsRepo?.map((e) => e.toJson()).toList(),
|
||||
'lastTrackerLibraryLocation': lastTrackerLibraryLocation,
|
||||
'mergeLibraryNavMobile': mergeLibraryNavMobile,
|
||||
'enableDiscordRpc': enableDiscordRpc,
|
||||
'hideDiscordRpcInIncognito': hideDiscordRpcInIncognito,
|
||||
'rpcShowReadingWatchingProgress': rpcShowReadingWatchingProgress,
|
||||
'rpcShowTitle': rpcShowTitle,
|
||||
'rpcShowCoverImage': rpcShowCoverImage,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -213,6 +213,7 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
bool _hasEndingSkip = false;
|
||||
bool _initSubtitleAndAudio = true;
|
||||
bool _includeSubtitles = false;
|
||||
int lastRpcTimestampUpdate = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
late final StreamSubscription<Duration> _currentPositionSub;
|
||||
|
||||
|
|
@ -221,6 +222,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
.duration
|
||||
.listen((duration) {
|
||||
_currentTotalDuration.value = duration;
|
||||
discordRpc.startChapterTimestamp(
|
||||
_currentPosition.value.inMilliseconds,
|
||||
duration.inMilliseconds,
|
||||
);
|
||||
});
|
||||
|
||||
bool get hasNextEpisode => _streamController.getEpisodeIndex().$1 != 0;
|
||||
|
|
@ -305,6 +310,14 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
if (_skipPhase.value != newPhase) _skipPhase.value = newPhase;
|
||||
}
|
||||
|
||||
void _updateRpcTimestamp() {
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
if (lastRpcTimestampUpdate + 10000 < now) {
|
||||
discordRpc.updateChapterTimestamp(_currentPosition.value.inMilliseconds);
|
||||
lastRpcTimestampUpdate = now;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
|
@ -338,6 +351,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
_setPlaybackSpeed(ref.read(defaultPlayBackSpeedStateProvider));
|
||||
if (ref.read(enableAniSkipStateProvider)) _initAniSkip();
|
||||
});
|
||||
discordRpc.showChapterDetails(ref, widget.episode);
|
||||
_currentPosition.addListener(_updateRpcTimestamp);
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
|
|
@ -404,6 +419,7 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
_currentPosition.removeListener(_updateRpcTimestamp);
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
_setCurrentPosition(true);
|
||||
_player.dispose();
|
||||
|
|
@ -422,6 +438,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
_setLandscapeMode(false);
|
||||
}
|
||||
_skipPhase.dispose();
|
||||
discordRpc.showIdleText();
|
||||
discordRpc.showOriginalTimestamp();
|
||||
_currentPosition.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
|
@ -1113,24 +1131,6 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: ValueListenableBuilder<bool>(
|
||||
valueListenable: _isDoubleSpeed,
|
||||
builder: (context, snapshot, _) {
|
||||
return Text.rich(
|
||||
TextSpan(
|
||||
children: snapshot
|
||||
? [
|
||||
WidgetSpan(child: Icon(Icons.fast_forward)),
|
||||
TextSpan(text: " 2X"),
|
||||
]
|
||||
: [],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
btnToShowChapterListDialog(
|
||||
|
|
@ -1272,6 +1272,46 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
height: context.height(1),
|
||||
resumeUponEnteringForegroundMode: true,
|
||||
),
|
||||
Stack(
|
||||
alignment: AlignmentDirectional.center,
|
||||
children: [
|
||||
Positioned(
|
||||
top: 30,
|
||||
child: ValueListenableBuilder<bool>(
|
||||
valueListenable: _isDoubleSpeed,
|
||||
builder: (context, snapshot, _) {
|
||||
return Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
style: TextStyle(
|
||||
background: Paint()
|
||||
..color = Theme.of(context).scaffoldBackgroundColor
|
||||
..strokeWidth = 30.0
|
||||
..strokeJoin = StrokeJoin.round
|
||||
..style = PaintingStyle.stroke,
|
||||
),
|
||||
children: snapshot
|
||||
? [
|
||||
TextSpan(
|
||||
text: " 2X ",
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(Icons.fast_forward),
|
||||
),
|
||||
]
|
||||
: [],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (enableAniSkip && (_hasOpeningSkip || _hasEndingSkip))
|
||||
Positioned(
|
||||
right: 0,
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ class CustomSeekBarState extends State<CustomSeekBar> {
|
|||
milliseconds: value.toInt() - position.inMilliseconds,
|
||||
),
|
||||
);
|
||||
widget.player.seek(Duration(milliseconds: value.toInt()));
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
tempPosition = Duration(milliseconds: value.toInt());
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ class _MainScreenState extends ConsumerState<MainScreen> {
|
|||
_initializeProviders();
|
||||
}
|
||||
});
|
||||
|
||||
discordRpc.connect(ref);
|
||||
}
|
||||
|
||||
void _initializeTimers() {
|
||||
|
|
@ -158,6 +160,7 @@ class _MainScreenState extends ConsumerState<MainScreen> {
|
|||
void dispose() {
|
||||
_backupTimer?.cancel();
|
||||
_syncTimer?.cancel();
|
||||
discordRpc.disconnect();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ class _MangaChapterPageGalleryState
|
|||
overlays: SystemUiOverlay.values,
|
||||
);
|
||||
}
|
||||
discordRpc.showIdleText();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -221,6 +222,7 @@ class _MangaChapterPageGalleryState
|
|||
_animation.addListener(() => _photoViewController.scale = _animation.value);
|
||||
_itemPositionsListener.itemPositions.addListener(_readProgressListener);
|
||||
_initCurrentIndex();
|
||||
discordRpc.showChapterDetails(ref, chapter);
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/modules/more/settings/general/providers/general_state_provider.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:mangayomi/utils/language.dart';
|
||||
import 'package:mangayomi/l10n/generated/app_localizations.dart';
|
||||
import 'package:super_sliver_list/super_sliver_list.dart';
|
||||
|
||||
class GeneralScreen extends ConsumerWidget {
|
||||
const GeneralScreen({super.key});
|
||||
|
|
@ -12,70 +10,63 @@ class GeneralScreen extends ConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final l10n = l10nLocalizations(context);
|
||||
final l10nLocale = ref.watch(l10nLocaleStateProvider);
|
||||
final enableDiscordRpc = ref.watch(enableDiscordRpcStateProvider);
|
||||
final hideDiscordRpcInIncognito = ref.watch(
|
||||
hideDiscordRpcInIncognitoStateProvider,
|
||||
);
|
||||
final rpcShowReadingWatchingProgress = ref.watch(
|
||||
rpcShowReadingWatchingProgressStateProvider,
|
||||
);
|
||||
final rpcShowTitleState = ref.watch(rpcShowTitleStateProvider);
|
||||
final rpcShowCoverImage = ref.watch(rpcShowCoverImageStateProvider);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(l10n!.general)),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(l10n.app_language),
|
||||
content: SizedBox(
|
||||
width: context.width(0.8),
|
||||
child: SuperListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: AppLocalizations.supportedLocales.length,
|
||||
itemBuilder: (context, index) {
|
||||
final locale =
|
||||
AppLocalizations.supportedLocales[index];
|
||||
return RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: locale,
|
||||
groupValue: l10nLocale,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(l10nLocaleStateProvider.notifier)
|
||||
.setLocale(locale);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: Text(
|
||||
completeLanguageName(locale.toLanguageTag()),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
SwitchListTile(
|
||||
value: enableDiscordRpc,
|
||||
title: Text(l10n.enable_discord_rpc),
|
||||
onChanged: (value) {
|
||||
ref.read(enableDiscordRpcStateProvider.notifier).set(value);
|
||||
if (value) {
|
||||
discordRpc.connect(ref);
|
||||
} else {
|
||||
discordRpc.disconnect();
|
||||
}
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
value: hideDiscordRpcInIncognito,
|
||||
title: Text(l10n.hide_discord_rpc_incognito),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(hideDiscordRpcInIncognitoStateProvider.notifier)
|
||||
.set(value);
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
value: rpcShowReadingWatchingProgress,
|
||||
title: Text(l10n.rpc_show_reading_watching_progress),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(rpcShowReadingWatchingProgressStateProvider.notifier)
|
||||
.set(value);
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
value: rpcShowTitleState,
|
||||
title: Text(l10n.rpc_show_title),
|
||||
onChanged: (value) {
|
||||
ref.read(rpcShowTitleStateProvider.notifier).set(value);
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
value: rpcShowCoverImage,
|
||||
title: Text(l10n.rpc_show_cover_image),
|
||||
onChanged: (value) {
|
||||
ref.read(rpcShowCoverImageStateProvider.notifier).set(value);
|
||||
},
|
||||
title: Text(l10n.app_language),
|
||||
subtitle: Text(
|
||||
completeLanguageName(l10nLocale.toLanguageTag()),
|
||||
style: TextStyle(fontSize: 11, color: context.secondaryColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'general_state_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
class EnableDiscordRpcState extends _$EnableDiscordRpcState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.enableDiscordRpc ?? true;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..enableDiscordRpc = value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class HideDiscordRpcInIncognitoState extends _$HideDiscordRpcInIncognitoState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.hideDiscordRpcInIncognito ?? true;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..hideDiscordRpcInIncognito = value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class RpcShowReadingWatchingProgressState
|
||||
extends _$RpcShowReadingWatchingProgressState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.rpcShowReadingWatchingProgress ?? true;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!..rpcShowReadingWatchingProgress = value,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class RpcShowTitleState extends _$RpcShowTitleState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.rpcShowTitle ?? true;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..rpcShowTitle = value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class RpcShowCoverImageState extends _$RpcShowCoverImageState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.rpcShowCoverImage ?? true;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..rpcShowCoverImage = value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'general_state_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$enableDiscordRpcStateHash() =>
|
||||
r'bc134787a33f362087befd5de85692812659faa0';
|
||||
|
||||
/// See also [EnableDiscordRpcState].
|
||||
@ProviderFor(EnableDiscordRpcState)
|
||||
final enableDiscordRpcStateProvider =
|
||||
AutoDisposeNotifierProvider<EnableDiscordRpcState, bool>.internal(
|
||||
EnableDiscordRpcState.new,
|
||||
name: r'enableDiscordRpcStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$enableDiscordRpcStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$EnableDiscordRpcState = AutoDisposeNotifier<bool>;
|
||||
String _$hideDiscordRpcInIncognitoStateHash() =>
|
||||
r'8e45104c34b1255b7a3d4a6f182bf43be9e2b93d';
|
||||
|
||||
/// See also [HideDiscordRpcInIncognitoState].
|
||||
@ProviderFor(HideDiscordRpcInIncognitoState)
|
||||
final hideDiscordRpcInIncognitoStateProvider =
|
||||
AutoDisposeNotifierProvider<HideDiscordRpcInIncognitoState, bool>.internal(
|
||||
HideDiscordRpcInIncognitoState.new,
|
||||
name: r'hideDiscordRpcInIncognitoStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$hideDiscordRpcInIncognitoStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$HideDiscordRpcInIncognitoState = AutoDisposeNotifier<bool>;
|
||||
String _$rpcShowReadingWatchingProgressStateHash() =>
|
||||
r'b4000c10234ce9070b44b535e9d10d16e6b7c0ec';
|
||||
|
||||
/// See also [RpcShowReadingWatchingProgressState].
|
||||
@ProviderFor(RpcShowReadingWatchingProgressState)
|
||||
final rpcShowReadingWatchingProgressStateProvider = AutoDisposeNotifierProvider<
|
||||
RpcShowReadingWatchingProgressState, bool>.internal(
|
||||
RpcShowReadingWatchingProgressState.new,
|
||||
name: r'rpcShowReadingWatchingProgressStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$rpcShowReadingWatchingProgressStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$RpcShowReadingWatchingProgressState = AutoDisposeNotifier<bool>;
|
||||
String _$rpcShowTitleStateHash() => r'9d7005af8968f61872fcc37979f5c54b745ffe65';
|
||||
|
||||
/// See also [RpcShowTitleState].
|
||||
@ProviderFor(RpcShowTitleState)
|
||||
final rpcShowTitleStateProvider =
|
||||
AutoDisposeNotifierProvider<RpcShowTitleState, bool>.internal(
|
||||
RpcShowTitleState.new,
|
||||
name: r'rpcShowTitleStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$rpcShowTitleStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$RpcShowTitleState = AutoDisposeNotifier<bool>;
|
||||
String _$rpcShowCoverImageStateHash() =>
|
||||
r'6ce1c61be44c0a6315fbb51a45ac6e47c3e49b33';
|
||||
|
||||
/// See also [RpcShowCoverImageState].
|
||||
@ProviderFor(RpcShowCoverImageState)
|
||||
final rpcShowCoverImageStateProvider =
|
||||
AutoDisposeNotifierProvider<RpcShowCoverImageState, bool>.internal(
|
||||
RpcShowCoverImageState.new,
|
||||
name: r'rpcShowCoverImageStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$rpcShowCoverImageStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$RpcShowCoverImageState = AutoDisposeNotifier<bool>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
|
@ -14,6 +14,11 @@ class SettingsScreen extends StatelessWidget {
|
|||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTileWidget(
|
||||
title: l10n.general,
|
||||
icon: Icons.settings,
|
||||
onTap: () => context.push('/general'),
|
||||
),
|
||||
ListTileWidget(
|
||||
title: l10n.appearance,
|
||||
subtitle: l10n.appearance_subtitle,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/modules/more/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/general/providers/general_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/widgets/list_tile_widget.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
|
||||
|
|
@ -12,12 +14,17 @@ class IncognitoModeWidget extends ConsumerWidget {
|
|||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final l10n = l10nLocalizations(context);
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
final hideDiscordRpcInIncognito = ref.watch(
|
||||
hideDiscordRpcInIncognitoStateProvider,
|
||||
);
|
||||
return ListTileWidget(
|
||||
onTap: () {
|
||||
if (incognitoMode == true) {
|
||||
ref.read(incognitoModeStateProvider.notifier).setIncognitoMode(false);
|
||||
if (hideDiscordRpcInIncognito) discordRpc.connect(ref);
|
||||
} else {
|
||||
ref.read(incognitoModeStateProvider.notifier).setIncognitoMode(true);
|
||||
if (hideDiscordRpcInIncognito) discordRpc.disconnect();
|
||||
}
|
||||
},
|
||||
icon: CupertinoIcons.eyeglasses,
|
||||
|
|
@ -27,6 +34,13 @@ class IncognitoModeWidget extends ConsumerWidget {
|
|||
value: incognitoMode,
|
||||
onChanged: (value) {
|
||||
ref.read(incognitoModeStateProvider.notifier).setIncognitoMode(value);
|
||||
if (hideDiscordRpcInIncognito) {
|
||||
if (value) {
|
||||
discordRpc.disconnect();
|
||||
} else {
|
||||
discordRpc.connect(ref);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
|
|||
overlays: SystemUiOverlay.values,
|
||||
);
|
||||
}
|
||||
discordRpc.showIdleText();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -113,6 +114,7 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
|
|||
fontSize = initFontSize;
|
||||
});
|
||||
});
|
||||
discordRpc.showChapterDetails(ref, chapter);
|
||||
}
|
||||
|
||||
late bool _isBookmarked = _readerController.getChapterBookmarked();
|
||||
|
|
|
|||
248
lib/utils/discord_rpc.dart
Normal file
248
lib/utils/discord_rpc.dart
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
import 'package:flutter_discord_rpc_fork/flutter_discord_rpc.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/modules/more/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/general/providers/general_state_provider.dart';
|
||||
|
||||
class DiscordRPC {
|
||||
/// Id of the Discord Application
|
||||
final String applicationId;
|
||||
|
||||
/// Whether it should reconnect to the discord client
|
||||
final bool autoRetry;
|
||||
|
||||
/// Seconds between each attempt to reconnect
|
||||
final int retryDelayInSeconds;
|
||||
|
||||
/// Start timestamp in millis
|
||||
final int startAt = DateTime.timestamp().millisecondsSinceEpoch;
|
||||
|
||||
/// Start timestamp in millis for the current chapter/episode
|
||||
int chapterStartAt = 0;
|
||||
|
||||
/// End timestamp in millis for the current chapter/episode
|
||||
int chapterEndAt = 0;
|
||||
|
||||
/// Temp var
|
||||
late bool rpcShowReadingWatchingProgress;
|
||||
|
||||
/// Instance of the current RPC activity
|
||||
final RpcActivity activity = RpcActivity(
|
||||
assets: const RPCAssets(largeImage: "app-icon", largeText: "Mangayomi"),
|
||||
buttons: [
|
||||
const RPCButton(
|
||||
label: "Get Mangayomi",
|
||||
url: "https://github.com/kodjodevf/mangayomi",
|
||||
),
|
||||
const RPCButton(
|
||||
label: "Join us",
|
||||
url: "https://discord.com/invite/EjfBuYahsP",
|
||||
),
|
||||
],
|
||||
details: "Idle",
|
||||
state: "-----",
|
||||
timestamps: RPCTimestamps(
|
||||
start: DateTime.timestamp().millisecondsSinceEpoch,
|
||||
),
|
||||
activityType: ActivityType.watching,
|
||||
);
|
||||
|
||||
DiscordRPC({
|
||||
required this.applicationId,
|
||||
this.autoRetry = true,
|
||||
this.retryDelayInSeconds = 10,
|
||||
});
|
||||
|
||||
Future<void> initialize() async {
|
||||
await FlutterDiscordRPC.initialize(applicationId);
|
||||
}
|
||||
|
||||
Future<void> connect(WidgetRef ref) async {
|
||||
final enableDiscordRpc = ref.read(enableDiscordRpcStateProvider);
|
||||
final incognitoMode = ref.read(incognitoModeStateProvider);
|
||||
final hideDiscordRpcInIncognito = ref.read(
|
||||
hideDiscordRpcInIncognitoStateProvider,
|
||||
);
|
||||
rpcShowReadingWatchingProgress = ref.read(
|
||||
rpcShowReadingWatchingProgressStateProvider,
|
||||
);
|
||||
if (enableDiscordRpc && (!hideDiscordRpcInIncognito || !incognitoMode)) {
|
||||
await FlutterDiscordRPC.instance.connect(
|
||||
autoRetry: autoRetry,
|
||||
retryDelay: Duration(seconds: retryDelayInSeconds),
|
||||
);
|
||||
await Future.delayed(Duration(seconds: 3));
|
||||
showIdleText();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> showIdleText() async {
|
||||
await updateActivity(
|
||||
details: "Idle",
|
||||
state: "-----",
|
||||
assets: const RPCAssets(largeImage: "app-icon", largeText: "Mangayomi"),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> showChapterDetails(WidgetRef ref, Chapter chapter) async {
|
||||
final status = chapter.manga.value!.itemType == ItemType.anime
|
||||
? "Watching"
|
||||
: "Reading";
|
||||
final title = chapter.manga.value!.name;
|
||||
final chapterTitle = chapter.name;
|
||||
final rpcShowTitle = ref.read(rpcShowTitleStateProvider);
|
||||
final rpcShowCoverImage = ref.read(rpcShowCoverImageStateProvider);
|
||||
await updateActivity(
|
||||
details: rpcShowTitle ? "$status $title" : "Idle",
|
||||
state: rpcShowTitle && rpcShowReadingWatchingProgress
|
||||
? chapterTitle
|
||||
: "-----",
|
||||
assets: rpcShowCoverImage
|
||||
? RPCAssets(
|
||||
largeImage: chapter.manga.value!.imageUrl,
|
||||
largeText: rpcShowTitle ? chapter.manga.value!.name : "-----",
|
||||
smallImage: "app-icon",
|
||||
smallText: "Mangayomi",
|
||||
)
|
||||
: const RPCAssets(largeImage: "app-icon", largeText: "Mangayomi"),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> showLargeImage() async {
|
||||
await updateActivity(
|
||||
assets: const RPCAssets(largeImage: "app-icon", largeText: "Mangayomi"),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> showSmallImage(String largeImage, String largeText) async {
|
||||
await updateActivity(
|
||||
assets: RPCAssets(
|
||||
largeImage: largeImage,
|
||||
largeText: largeText,
|
||||
smallImage: "app-icon",
|
||||
smallText: "Mangayomi",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> showOriginalTimestamp() async {
|
||||
await updateActivity(timestamps: RPCTimestamps(start: startAt));
|
||||
}
|
||||
|
||||
Future<void> startChapterTimestamp(
|
||||
int offsetInMillis,
|
||||
int durationInMillis,
|
||||
) async {
|
||||
if (!rpcShowReadingWatchingProgress) {
|
||||
return;
|
||||
}
|
||||
chapterStartAt = DateTime.timestamp().millisecondsSinceEpoch;
|
||||
chapterEndAt =
|
||||
DateTime.timestamp().millisecondsSinceEpoch + durationInMillis;
|
||||
await updateActivity(
|
||||
timestamps: RPCTimestamps(
|
||||
start: chapterStartAt,
|
||||
end: chapterEndAt - offsetInMillis,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateChapterTimestamp(int newOffsetInMillis) async {
|
||||
if (!rpcShowReadingWatchingProgress) {
|
||||
return;
|
||||
}
|
||||
await updateActivity(
|
||||
timestamps: RPCTimestamps(
|
||||
start: chapterStartAt,
|
||||
end: chapterEndAt - newOffsetInMillis,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateActivity({
|
||||
String? state,
|
||||
String? details,
|
||||
RPCTimestamps? timestamps,
|
||||
RPCParty? party,
|
||||
RPCAssets? assets,
|
||||
RPCSecrets? secrets,
|
||||
List<RPCButton>? buttons,
|
||||
ActivityType? activityType,
|
||||
}) async {
|
||||
if (!FlutterDiscordRPC.instance.isConnected) {
|
||||
return;
|
||||
}
|
||||
if (state != null) {
|
||||
activity.state = state;
|
||||
}
|
||||
if (details != null) {
|
||||
activity.details = details;
|
||||
}
|
||||
if (timestamps != null) {
|
||||
activity.timestamps = timestamps;
|
||||
}
|
||||
if (party != null) {
|
||||
activity.party = party;
|
||||
}
|
||||
if (assets != null) {
|
||||
activity.assets = assets;
|
||||
}
|
||||
if (secrets != null) {
|
||||
activity.secrets = secrets;
|
||||
}
|
||||
if (buttons != null) {
|
||||
activity.buttons = buttons;
|
||||
}
|
||||
if (activityType != null) {
|
||||
activity.activityType = activityType;
|
||||
}
|
||||
await FlutterDiscordRPC.instance.setActivity(
|
||||
activity: activity.toRPCActivity(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> disconnect() async {
|
||||
await FlutterDiscordRPC.instance.disconnect();
|
||||
}
|
||||
|
||||
Future<void> destroy() async {
|
||||
await FlutterDiscordRPC.instance.disconnect();
|
||||
await FlutterDiscordRPC.instance.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class RpcActivity {
|
||||
String? state;
|
||||
String? details;
|
||||
RPCTimestamps? timestamps;
|
||||
RPCParty? party;
|
||||
RPCAssets? assets;
|
||||
RPCSecrets? secrets;
|
||||
List<RPCButton>? buttons;
|
||||
ActivityType? activityType;
|
||||
|
||||
RpcActivity({
|
||||
this.state,
|
||||
this.details,
|
||||
this.timestamps,
|
||||
this.party,
|
||||
this.assets,
|
||||
this.secrets,
|
||||
this.buttons,
|
||||
this.activityType,
|
||||
});
|
||||
|
||||
RPCActivity toRPCActivity() {
|
||||
return RPCActivity(
|
||||
state: state,
|
||||
details: details,
|
||||
timestamps: timestamps,
|
||||
party: party,
|
||||
assets: assets,
|
||||
secrets: secrets,
|
||||
buttons: buttons,
|
||||
activityType: activityType,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
flutter_discord_rpc_fork
|
||||
rust_lib_mangayomi
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -549,6 +549,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
flutter_discord_rpc_fork:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_discord_rpc_fork
|
||||
sha256: a32b3d5871af591ec73b65feb2818f3e3d4e05d46b9903c6f117b03865a86282
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
flutter_inappwebview:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -94,6 +94,10 @@ dependencies:
|
|||
d4rt: 0.0.9
|
||||
hive: ^2.2.3
|
||||
hive_flutter: ^1.1.0
|
||||
flutter_discord_rpc_fork:
|
||||
git:
|
||||
url: https://github.com/Schnitzel5/flutter-discord-rpc.git
|
||||
ref: main
|
||||
|
||||
dependency_overrides:
|
||||
ffi: ^2.1.3
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
flutter_discord_rpc_fork
|
||||
rust_lib_mangayomi
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue