Skip to content

Commit

Permalink
[timetable] wallpaper support on web
Browse files Browse the repository at this point in the history
  • Loading branch information
liplum committed Apr 17, 2024
1 parent dc130ad commit 4cbf9b9
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 41 deletions.
40 changes: 17 additions & 23 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,6 @@ class _MimirAppState extends ConsumerState<MimirApp> {
);
late final router = buildRouter($routingConfig);

@override
void initState() {
super.initState();
if (!kIsWeb) {
fitSystemScreenshot.init();
}
}

@override
void dispose() {
fitSystemScreenshot.release();
super.dispose();
}

@override
void didChangeDependencies() {
// precache timetable background file
if (Settings.timetable.backgroundImage?.enabled == true) {
precacheImage(FileImage(Files.timetable.backgroundFile), context);
}
super.didChangeDependencies();
}

@override
Widget build(BuildContext context) {
final demoMode = ref.watch(Dev.$demoMode);
Expand Down Expand Up @@ -139,6 +116,9 @@ class _PostServiceRunnerState extends ConsumerState<_PostServiceRunner> {
@override
void initState() {
super.initState();
if (!kIsWeb) {
fitSystemScreenshot.init();
}
if (!kIsWeb) {
Future.delayed(Duration.zero).then((value) async {
await checkAppUpdate(
Expand Down Expand Up @@ -168,9 +148,23 @@ class _PostServiceRunnerState extends ConsumerState<_PostServiceRunner> {
});
}

@override
void didChangeDependencies() {
// precache timetable background file
final timetableBk = Settings.timetable.backgroundImage;
if (timetableBk != null && timetableBk.enabled) {
if (kIsWeb) {
precacheImage(NetworkImage(timetableBk.path), context);
} else {
precacheImage(FileImage(Files.timetable.backgroundFile), context);
}
}
super.didChangeDependencies();
}
@override
void dispose() {
$appLink?.cancel();
fitSystemScreenshot.release();
super.dispose();
}

Expand Down
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sit/files.dart';
import 'package:sit/migration/foundation.dart';
Expand Down Expand Up @@ -36,6 +37,7 @@ void main() async {
// debugRepaintTextRainbowEnabled = true;
// debugPaintSizeEnabled = true;
WidgetsFlutterBinding.ensureInitialized();
GoRouter.optionURLReflectsImperativeAPIs = kDebugMode;
final prefs = await SharedPreferences.getInstance();
final lastSize = prefs.getLastWindowSize();
await DesktopInit.init(size: lastSize);
Expand Down
90 changes: 74 additions & 16 deletions lib/timetable/page/p13n/background.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import 'package:rettulf/rettulf.dart';
import 'package:sit/design/adaptive/editor.dart';
import 'package:sit/design/adaptive/multiplatform.dart';
import 'package:sit/design/widgets/common.dart';
import 'package:sit/files.dart';
Expand All @@ -17,6 +19,7 @@ import 'package:sit/widgets/modal_image_view.dart';
import 'package:universal_platform/universal_platform.dart';
import "../../i18n.dart";

/// Persist changes to storage before route popping
class TimetableBackgroundEditor extends StatefulWidget {
const TimetableBackgroundEditor({super.key});

Expand All @@ -35,7 +38,9 @@ class _TimetableBackgroundEditorState extends State<TimetableBackgroundEditor> w
_TimetableBackgroundEditorState() {
final bk = Settings.timetable.backgroundImage;
rawPath = bk?.path;
renderImageFile = bk?.path == null ? null : Files.timetable.backgroundFile;
if (!kIsWeb) {
renderImageFile = bk?.path == null ? null : Files.timetable.backgroundFile;
}
opacity = bk?.opacity ?? 1.0;
repeat = bk?.repeat ?? true;
antialias = bk?.antialias ?? true;
Expand Down Expand Up @@ -71,7 +76,7 @@ class _TimetableBackgroundEditorState extends State<TimetableBackgroundEditor> w
SliverList.list(children: [
buildImage().padH(10),
buildToolBar().padV(4),
if (Dev.on && rawPath != null)
if (rawPath != null && (Dev.on || (UniversalPlatform.isDesktop || kIsWeb)))
ListTile(
title: "Selected image".text(),
subtitle: rawPath.text(),
Expand All @@ -86,6 +91,28 @@ class _TimetableBackgroundEditorState extends State<TimetableBackgroundEditor> w
}

Future<void> onSave() async {
if (kIsWeb) {
await onSaveWeb();
} else {
await onSaveIo();
}
}

Future<void> onSaveWeb() async {
final background = buildBackgroundImage();
if (background == null) {
Settings.timetable.backgroundImage = background;
context.pop(null);
return;
}
final img = NetworkImage(background.path);
Settings.timetable.backgroundImage = background;
await precacheImage(img, context);
if (!mounted) return;
context.pop(background);
}

Future<void> onSaveIo() async {
final background = buildBackgroundImage();
final img = FileImage(Files.timetable.backgroundFile);
if (background == null) {
Expand All @@ -96,19 +123,19 @@ class _TimetableBackgroundEditorState extends State<TimetableBackgroundEditor> w
Settings.timetable.backgroundImage = null;
if (!mounted) return;
context.pop(null);
} else {
final renderImageFile = this.renderImageFile;
if (renderImageFile == null) return;
Settings.timetable.backgroundImage = background;
if (renderImageFile.path != Files.timetable.backgroundFile.path) {
await copyCompressedImageToTarget(source: renderImageFile, target: Files.timetable.backgroundFile.path);
await img.evict();
if (!mounted) return;
await precacheImage(img, context);
}
return;
}
final renderImageFile = this.renderImageFile;
if (renderImageFile == null) return;
Settings.timetable.backgroundImage = background;
if (renderImageFile.path != Files.timetable.backgroundFile.path) {
await copyCompressedImageToTarget(source: renderImageFile, target: Files.timetable.backgroundFile.path);
await img.evict();
if (!mounted) return;
context.pop(background);
await precacheImage(img, context);
}
if (!mounted) return;
context.pop(background);
}

Future<void> copyCompressedImageToTarget({
Expand All @@ -127,6 +154,26 @@ class _TimetableBackgroundEditorState extends State<TimetableBackgroundEditor> w
}
}

Future<void> chooseImage() async {
if (kIsWeb) {
await inputImageUrl();
} else {
await pickImage();
}
}

Future<void> inputImageUrl() async {
final url = await Editor.showStringEditor(
context,
desc: "Image URL",
initial: rawPath ?? "",
);
if (url == null) return;
setState(() {
rawPath = url;
});
}

Future<void> pickImage() async {
final picker = ImagePicker();
final XFile? fi = await picker.pickImage(
Expand Down Expand Up @@ -156,7 +203,7 @@ class _TimetableBackgroundEditorState extends State<TimetableBackgroundEditor> w
Widget buildToolBar() {
return [
FilledButton.icon(
onPressed: pickImage,
onPressed: chooseImage,
icon: Icon(context.icons.create),
label: i18n.choose.text(),
),
Expand Down Expand Up @@ -185,20 +232,31 @@ class _TimetableBackgroundEditorState extends State<TimetableBackgroundEditor> w
Widget buildPreviewBoxContent() {
final renderImageFile = this.renderImageFile;
final height = context.mediaQuery.size.height / 3;
final rawPath = this.rawPath;
final filterQuality = antialias ? FilterQuality.low : FilterQuality.none;
if (renderImageFile != null) {
return ModalImageViewer(
child: Image.file(
renderImageFile,
opacity: $opacity,
height: height,
filterQuality: antialias ? FilterQuality.low : FilterQuality.none,
filterQuality: filterQuality,
),
);
} else if (kIsWeb && rawPath != null) {
return ModalImageViewer(
child: Image.network(
rawPath,
opacity: $opacity,
height: height,
filterQuality: filterQuality,
),
);
} else {
return LeavingBlank(
icon: Icons.add_photo_alternate_outlined,
desc: i18n.p13n.background.pickTip,
onIconTap: renderImageFile == null ? pickImage : null,
onIconTap: renderImageFile == null ? chooseImage : null,
).sized(h: height);
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/timetable/page/p13n/cell_style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import '../../widgets/style.dart';
import '../../i18n.dart';
import 'palette.dart';

/// Persist changes to storage before route popping
class TimetableCellStyleEditor extends StatefulWidget {
const TimetableCellStyleEditor({super.key});

Expand Down
16 changes: 14 additions & 2 deletions lib/timetable/widgets/timetable/board.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:rettulf/rettulf.dart';
import 'package:sit/files.dart';
Expand Down Expand Up @@ -97,12 +98,23 @@ class _TimetableBackgroundState extends State<TimetableBackground> with SingleTi
@override
Widget build(BuildContext context) {
final bk = widget.background;
final filterQuality = bk.antialias ? FilterQuality.low : FilterQuality.none;
final repeat = bk.repeat ? ImageRepeat.repeat : ImageRepeat.noRepeat;
if (kIsWeb) {
return Image.network(
key: ValueKey(bk.path),
bk.path,
opacity: $opacity,
filterQuality: filterQuality,
repeat: repeat,
);
}
return Image.file(
key: ValueKey(bk.path),
Files.timetable.backgroundFile,
opacity: $opacity,
filterQuality: bk.antialias ? FilterQuality.low : FilterQuality.none,
repeat: bk.repeat ? ImageRepeat.repeat : ImageRepeat.noRepeat,
filterQuality: filterQuality,
repeat: repeat,
);
}
}

0 comments on commit 4cbf9b9

Please sign in to comment.