forked from Cutlery/immich
Compare commits
6 Commits
main
...
chore/auto
Author | SHA1 | Date | |
---|---|---|---|
|
b2b9dcf84e | ||
|
85b72d1d74 | ||
|
2a8e3e4925 | ||
|
a9631dace0 | ||
|
ad9454f122 | ||
|
3905aa7097 |
10
.github/workflows/build-mobile.yml
vendored
10
.github/workflows/build-mobile.yml
vendored
@ -37,15 +37,15 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-java@v4
|
- uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: "zulu"
|
distribution: 'zulu'
|
||||||
java-version: "11.0.21+9"
|
java-version: '17'
|
||||||
cache: "gradle"
|
cache: 'gradle'
|
||||||
|
|
||||||
- name: Setup Flutter SDK
|
- name: Setup Flutter SDK
|
||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: "stable"
|
channel: 'stable'
|
||||||
flutter-version: "3.19.3"
|
flutter-version: '3.19.3'
|
||||||
cache: true
|
cache: true
|
||||||
|
|
||||||
- name: Create the Keystore
|
- name: Create the Keystore
|
||||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -221,7 +221,7 @@ jobs:
|
|||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
flutter-version: '3.16.9'
|
flutter-version: '3.19.3'
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
run: flutter test -j 1
|
run: flutter test -j 1
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
|
plugins {
|
||||||
|
id "com.android.application"
|
||||||
|
id "kotlin-android"
|
||||||
|
id "dev.flutter.flutter-gradle-plugin"
|
||||||
|
id "kotlin-kapt"
|
||||||
|
}
|
||||||
|
|
||||||
def localProperties = new Properties()
|
def localProperties = new Properties()
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
if (localPropertiesFile.exists()) {
|
if (localPropertiesFile.exists()) {
|
||||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
localPropertiesFile.withInputStream { localProperties.load(it) }
|
||||||
localProperties.load(reader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
|
||||||
if (flutterRoot == null) {
|
|
||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
@ -21,18 +21,12 @@ if (flutterVersionName == null) {
|
|||||||
flutterVersionName = '1.0'
|
flutterVersionName = '1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'kotlin-kapt'
|
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
|
||||||
|
|
||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
if (keystorePropertiesFile.exists()) {
|
if (keystorePropertiesFile.exists()) {
|
||||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
keystorePropertiesFile.withInputStream { keystoreProperties.load(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 34
|
compileSdkVersion 34
|
||||||
|
|
||||||
@ -50,7 +44,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
|
||||||
applicationId "app.alextran.immich"
|
applicationId "app.alextran.immich"
|
||||||
minSdkVersion 26
|
minSdkVersion 26
|
||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
@ -88,6 +81,13 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
def kotlin_version = '1.9.23'
|
||||||
|
def kotlin_coroutines_version = '1.8.0'
|
||||||
|
def work_version = '2.9.0'
|
||||||
|
def concurrent_version = '1.1.0'
|
||||||
|
def guava_version = '33.1.0-android'
|
||||||
|
def glide_version = '4.16.0'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||||
implementation "androidx.work:work-runtime-ktx:$work_version"
|
implementation "androidx.work:work-runtime-ktx:$work_version"
|
||||||
|
@ -276,7 +276,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
|||||||
private const val NOTIFICATION_CHANNEL_ERROR_ID = "immich/backgroundServiceError"
|
private const val NOTIFICATION_CHANNEL_ERROR_ID = "immich/backgroundServiceError"
|
||||||
private const val NOTIFICATION_DEFAULT_TITLE = "Immich"
|
private const val NOTIFICATION_DEFAULT_TITLE = "Immich"
|
||||||
private const val NOTIFICATION_ID = 1
|
private const val NOTIFICATION_ID = 1
|
||||||
private const val NOTIFICATION_ERROR_ID = 2
|
private const val NOTIFICATION_ERROR_ID = 2
|
||||||
private const val NOTIFICATION_DETAIL_ID = 3
|
private const val NOTIFICATION_DETAIL_ID = 3
|
||||||
private const val ONE_MINUTE = 60000L
|
private const val ONE_MINUTE = 60000L
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
|||||||
val workInfoList = workInfoFuture.get(1000, TimeUnit.MILLISECONDS)
|
val workInfoList = workInfoFuture.get(1000, TimeUnit.MILLISECONDS)
|
||||||
if (workInfoList != null) {
|
if (workInfoList != null) {
|
||||||
for (workInfo in workInfoList) {
|
for (workInfo in workInfoList) {
|
||||||
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
|
if (workInfo.state == WorkInfo.State.ENQUEUED) {
|
||||||
val workRequest = buildWorkRequest(requireWifi, requireCharging)
|
val workRequest = buildWorkRequest(requireWifi, requireCharging)
|
||||||
wm.enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.REPLACE, workRequest)
|
wm.enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.REPLACE, workRequest)
|
||||||
Log.d(TAG, "updateBackupWorker updated BackupWorker constraints")
|
Log.d(TAG, "updateBackupWorker updated BackupWorker constraints")
|
||||||
@ -346,7 +346,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
|||||||
.setRequiresBatteryNotLow(true)
|
.setRequiresBatteryNotLow(true)
|
||||||
.setRequiresCharging(requireCharging)
|
.setRequiresCharging(requireCharging)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
val work = OneTimeWorkRequest.Builder(BackupWorker::class.java)
|
val work = OneTimeWorkRequest.Builder(BackupWorker::class.java)
|
||||||
.setConstraints(constraints)
|
.setConstraints(constraints)
|
||||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, ONE_MINUTE, TimeUnit.MILLISECONDS)
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, ONE_MINUTE, TimeUnit.MILLISECONDS)
|
||||||
@ -359,4 +359,4 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val TAG = "BackupWorker"
|
private const val TAG = "BackupWorker"
|
||||||
|
@ -1,21 +1,3 @@
|
|||||||
buildscript {
|
|
||||||
ext.kotlin_version = '1.8.20'
|
|
||||||
ext.kotlin_coroutines_version = '1.7.1'
|
|
||||||
ext.work_version = '2.7.1'
|
|
||||||
ext.concurrent_version = '1.1.0'
|
|
||||||
ext.guava_version = '33.0.0-android'
|
|
||||||
ext.glide_version = '4.14.2'
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
@ -34,3 +16,7 @@ subprojects {
|
|||||||
tasks.register("clean", Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.named('wrapper') {
|
||||||
|
distributionType = Wrapper.DistributionType.ALL
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-all.zip
|
||||||
distributionSha256Sum=6001aba9b2204d26fa25a5800bb9382cf3ee01ccb78fe77317b2872336eb2f80
|
distributionSha256Sum=fe696c020f241a5f69c30f763c5a7f38eec54b490db19cd2b0962dda420d7d12
|
@ -1,11 +1,26 @@
|
|||||||
include ':app'
|
pluginManagement {
|
||||||
|
def flutterSdkPath = {
|
||||||
|
def properties = new Properties()
|
||||||
|
file("local.properties").withInputStream { properties.load(it) }
|
||||||
|
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
|
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||||
|
return flutterSdkPath
|
||||||
|
}()
|
||||||
|
|
||||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||||
def properties = new Properties()
|
|
||||||
|
|
||||||
assert localPropertiesFile.exists()
|
repositories {
|
||||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
plugins {
|
||||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
id "com.android.application" version "7.4.2" apply false
|
||||||
|
id "org.jetbrains.kotlin.android" version "1.9.23" apply false
|
||||||
|
id "org.jetbrains.kotlin.kapt" version "1.9.23" apply false
|
||||||
|
}
|
||||||
|
|
||||||
|
include ":app"
|
||||||
|
@ -275,7 +275,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () async => await context.popRoute(),
|
onPressed: () async => await context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
splashRadius: 25,
|
splashRadius: 25,
|
||||||
);
|
);
|
||||||
|
@ -184,7 +184,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(Icons.arrow_back_ios_new_rounded),
|
icon: const Icon(Icons.arrow_back_ios_new_rounded),
|
||||||
onPressed: () => context.popRoute(null),
|
onPressed: () => context.maybePop(null),
|
||||||
),
|
),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: Text("translated_text_options".tr()),
|
title: Text("translated_text_options".tr()),
|
||||||
|
@ -216,7 +216,7 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
selectedAssets.value = {};
|
selectedAssets.value = {};
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.close_rounded),
|
icon: const Icon(Icons.close_rounded),
|
||||||
),
|
),
|
||||||
|
@ -23,7 +23,7 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
|||||||
final sharedUsersList = useState<Set<User>>({});
|
final sharedUsersList = useState<Set<User>>({});
|
||||||
|
|
||||||
addNewUsersHandler() {
|
addNewUsersHandler() {
|
||||||
context.popRoute(sharedUsersList.value.map((e) => e.id).toList());
|
context.maybePop(sharedUsersList.value.map((e) => e.id).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTileIcon(User user) {
|
buildTileIcon(User user) {
|
||||||
@ -124,7 +124,7 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
|||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(Icons.close_rounded),
|
icon: const Icon(Icons.close_rounded),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.popRoute(null);
|
context.maybePop(null);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -36,7 +36,7 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
|||||||
await ref.watch(sharedAlbumProvider.notifier).getAllSharedAlbums();
|
await ref.watch(sharedAlbumProvider.notifier).getAllSharedAlbums();
|
||||||
// ref.watch(assetSelectionProvider.notifier).removeAll();
|
// ref.watch(assetSelectionProvider.notifier).removeAll();
|
||||||
ref.watch(albumTitleProvider.notifier).clearAlbumTitle();
|
ref.watch(albumTitleProvider.notifier).clearAlbumTitle();
|
||||||
context.popRoute(true);
|
context.maybePop(true);
|
||||||
context
|
context
|
||||||
.navigateTo(const TabControllerRoute(children: [SharingRoute()]));
|
.navigateTo(const TabControllerRoute(children: [SharingRoute()]));
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
|||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(Icons.close_rounded),
|
icon: const Icon(Icons.close_rounded),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -17,7 +17,7 @@ class ArchivePage extends HookConsumerWidget {
|
|||||||
final count = archivedAssets.value?.totalAssets.toString() ?? "?";
|
final count = archivedAssets.value?.totalAssets.toString() ?? "?";
|
||||||
return AppBar(
|
return AppBar(
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
|
@ -120,7 +120,7 @@ class BottomGalleryBar extends ConsumerWidget {
|
|||||||
if (isDeleted && isParent) {
|
if (isDeleted && isParent) {
|
||||||
if (totalAssets == 1) {
|
if (totalAssets == 1) {
|
||||||
// Handle only one asset
|
// Handle only one asset
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
} else {
|
} else {
|
||||||
// Go to next page otherwise
|
// Go to next page otherwise
|
||||||
controller.nextPage(
|
controller.nextPage(
|
||||||
@ -191,7 +191,7 @@ class BottomGalleryBar extends ConsumerWidget {
|
|||||||
stackElements.elementAt(stackIndex),
|
stackElements.elementAt(stackIndex),
|
||||||
);
|
);
|
||||||
ctx.pop();
|
ctx.pop();
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
},
|
},
|
||||||
title: const Text(
|
title: const Text(
|
||||||
"viewer_stack_use_as_main_asset",
|
"viewer_stack_use_as_main_asset",
|
||||||
@ -218,7 +218,7 @@ class BottomGalleryBar extends ConsumerWidget {
|
|||||||
childrenToRemove: [asset],
|
childrenToRemove: [asset],
|
||||||
);
|
);
|
||||||
ctx.pop();
|
ctx.pop();
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
} else {
|
} else {
|
||||||
await ref.read(assetStackServiceProvider).updateStack(
|
await ref.read(assetStackServiceProvider).updateStack(
|
||||||
asset,
|
asset,
|
||||||
@ -246,7 +246,7 @@ class BottomGalleryBar extends ConsumerWidget {
|
|||||||
childrenToRemove: stack,
|
childrenToRemove: stack,
|
||||||
);
|
);
|
||||||
ctx.pop();
|
ctx.pop();
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
},
|
},
|
||||||
title: const Text(
|
title: const Text(
|
||||||
"viewer_unstack",
|
"viewer_unstack",
|
||||||
@ -277,7 +277,7 @@ class BottomGalleryBar extends ConsumerWidget {
|
|||||||
handleArchive() {
|
handleArchive() {
|
||||||
ref.read(assetProvider.notifier).toggleArchive([asset]);
|
ref.read(assetProvider.notifier).toggleArchive([asset]);
|
||||||
if (isParent) {
|
if (isParent) {
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
removeAssetFromStack();
|
removeAssetFromStack();
|
||||||
|
@ -147,7 +147,7 @@ class TopControlAppBar extends HookConsumerWidget {
|
|||||||
Widget buildBackButton() {
|
Widget buildBackButton() {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.arrow_back_ios_new_rounded,
|
Icons.arrow_back_ios_new_rounded,
|
||||||
|
@ -173,7 +173,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
final ratio = d.dy / max(d.dx.abs(), 1);
|
final ratio = d.dy / max(d.dx.abs(), 1);
|
||||||
if (d.dy > sensitivity && ratio > ratioThreshold) {
|
if (d.dy > sensitivity && ratio > ratioThreshold) {
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
} else if (d.dy < -sensitivity && ratio < -ratioThreshold) {
|
} else if (d.dy < -sensitivity && ratio < -ratioThreshold) {
|
||||||
showInfo();
|
showInfo();
|
||||||
}
|
}
|
||||||
@ -260,12 +260,9 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return PopScope(
|
return PopScope(
|
||||||
canPop: false,
|
// Change immersive mode back to normal "edgeToEdge" mode
|
||||||
onPopInvoked: (_) {
|
onPopInvoked: (_) =>
|
||||||
// Change immersive mode back to normal "edgeToEdge" mode
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge),
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
|
||||||
context.pop();
|
|
||||||
},
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
body: Stack(
|
body: Stack(
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@ -11,8 +10,6 @@ import 'package:immich_mobile/shared/models/asset.dart';
|
|||||||
import 'package:immich_mobile/shared/ui/delayed_loading_indicator.dart';
|
import 'package:immich_mobile/shared/ui/delayed_loading_indicator.dart';
|
||||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||||
|
|
||||||
@RoutePage()
|
|
||||||
// ignore: must_be_immutable
|
|
||||||
class VideoViewerPage extends HookConsumerWidget {
|
class VideoViewerPage extends HookConsumerWidget {
|
||||||
final Asset asset;
|
final Asset asset;
|
||||||
final bool isMotionVideo;
|
final bool isMotionVideo;
|
||||||
|
@ -54,7 +54,7 @@ class AlbumPreviewPage extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_new_rounded),
|
icon: const Icon(Icons.arrow_back_ios_new_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -191,7 +191,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
title: const Text(
|
title: const Text(
|
||||||
|
@ -260,7 +260,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ref.watch(websocketProvider.notifier).listenUploadEvent();
|
ref.watch(websocketProvider.notifier).listenUploadEvent();
|
||||||
context.popRoute(true);
|
context.maybePop(true);
|
||||||
},
|
},
|
||||||
splashRadius: 24,
|
splashRadius: 24,
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
|
@ -13,7 +13,7 @@ class BackupOptionsPage extends StatelessWidget {
|
|||||||
elevation: 0,
|
elevation: 0,
|
||||||
title: const Text("backup_options_page_title").tr(),
|
title: const Text("backup_options_page_title").tr(),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(true),
|
onPressed: () => context.maybePop(true),
|
||||||
splashRadius: 24,
|
splashRadius: 24,
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_back_ios_rounded,
|
Icons.arrow_back_ios_rounded,
|
||||||
|
@ -23,7 +23,7 @@ class FailedBackupStatusPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.popRoute(true);
|
context.maybePop(true);
|
||||||
},
|
},
|
||||||
splashRadius: 24,
|
splashRadius: 24,
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
|
@ -15,7 +15,7 @@ class FavoritesPage extends HookConsumerWidget {
|
|||||||
AppBar buildAppBar() {
|
AppBar buildAppBar() {
|
||||||
return AppBar(
|
return AppBar(
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
|
@ -41,7 +41,7 @@ class MapLocationPickerPage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onClose([LatLng? selected]) {
|
void onClose([LatLng? selected]) {
|
||||||
context.popRoute(selected);
|
context.maybePop(selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getCurrentLocation() async {
|
Future<void> getCurrentLocation() async {
|
||||||
|
@ -50,7 +50,7 @@ class _NonSelectionRow extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
shape: const CircleBorder(),
|
shape: const CircleBorder(),
|
||||||
),
|
),
|
||||||
|
@ -152,7 +152,7 @@ class MemoryPage extends HookConsumerWidget {
|
|||||||
final offset = notification.metrics.pixels;
|
final offset = notification.metrics.pixels;
|
||||||
if (isEpiloguePage &&
|
if (isEpiloguePage &&
|
||||||
(offset > notification.metrics.maxScrollExtent + 150)) {
|
(offset > notification.metrics.maxScrollExtent + 150)) {
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ class MemoryPage extends HookConsumerWidget {
|
|||||||
// auto_route doesn't invoke pop scope, so
|
// auto_route doesn't invoke pop scope, so
|
||||||
// turn off full screen mode here
|
// turn off full screen mode here
|
||||||
// https://github.com/Milad-Akarie/auto_route_library/issues/1799
|
// https://github.com/Milad-Akarie/auto_route_library/issues/1799
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
SystemChrome.setEnabledSystemUIMode(
|
SystemChrome.setEnabledSystemUIMode(
|
||||||
SystemUiMode.edgeToEdge,
|
SystemUiMode.edgeToEdge,
|
||||||
);
|
);
|
||||||
|
@ -176,7 +176,7 @@ class PermissionOnboardingPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('permission_onboarding_back').tr(),
|
child: const Text('permission_onboarding_back').tr(),
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -18,7 +18,7 @@ class AllMotionPhotosPage extends HookConsumerWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('motion_photos_page_title').tr(),
|
title: const Text('motion_photos_page_title').tr(),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -21,7 +21,7 @@ class AllPeoplePage extends HookConsumerWidget {
|
|||||||
'all_people_page_title',
|
'all_people_page_title',
|
||||||
).tr(),
|
).tr(),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -15,7 +15,7 @@ class AllVideosPage extends HookConsumerWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('all_videos_page_title').tr(),
|
title: const Text('all_videos_page_title').tr(),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -23,7 +23,7 @@ class CuratedLocationPage extends HookConsumerWidget {
|
|||||||
'curated_location_page_title',
|
'curated_location_page_title',
|
||||||
).tr(),
|
).tr(),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -102,7 +102,7 @@ class PersonResultPage extends HookConsumerWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(name.value),
|
title: Text(name.value),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -18,7 +18,7 @@ class RecentlyAddedPage extends HookConsumerWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('recently_added_page_title').tr(),
|
title: const Text('recently_added_page_title').tr(),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () => context.popRoute(),
|
onPressed: () => context.maybePop(),
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -319,7 +319,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
|||||||
alignment: Alignment.bottomRight,
|
alignment: Alignment.bottomRight,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
},
|
},
|
||||||
child: const Text(
|
child: const Text(
|
||||||
"share_done",
|
"share_done",
|
||||||
@ -422,7 +422,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
|||||||
changeExpiry: changeExpiry,
|
changeExpiry: changeExpiry,
|
||||||
);
|
);
|
||||||
ref.invalidate(sharedLinksStateProvider);
|
ref.invalidate(sharedLinksStateProvider);
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -143,7 +143,7 @@ class TrashPage extends HookConsumerWidget {
|
|||||||
return AppBar(
|
return AppBar(
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: !selectionEnabledHook.value
|
onPressed: !selectionEnabledHook.value
|
||||||
? () => context.popRoute()
|
? () => context.maybePop()
|
||||||
: () {
|
: () {
|
||||||
selectionEnabledHook.value = false;
|
selectionEnabledHook.value = false;
|
||||||
selection.value = {};
|
selection.value = {};
|
||||||
|
@ -20,7 +20,6 @@ import 'package:immich_mobile/modules/album/views/select_user_for_sharing_page.d
|
|||||||
import 'package:immich_mobile/modules/album/views/sharing_page.dart';
|
import 'package:immich_mobile/modules/album/views/sharing_page.dart';
|
||||||
import 'package:immich_mobile/modules/archive/views/archive_page.dart';
|
import 'package:immich_mobile/modules/archive/views/archive_page.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/views/gallery_viewer.dart';
|
import 'package:immich_mobile/modules/asset_viewer/views/gallery_viewer.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart';
|
|
||||||
import 'package:immich_mobile/modules/backup/views/album_preview_page.dart';
|
import 'package:immich_mobile/modules/backup/views/album_preview_page.dart';
|
||||||
import 'package:immich_mobile/modules/backup/views/backup_album_selection_page.dart';
|
import 'package:immich_mobile/modules/backup/views/backup_album_selection_page.dart';
|
||||||
import 'package:immich_mobile/modules/backup/views/backup_controller_page.dart';
|
import 'package:immich_mobile/modules/backup/views/backup_controller_page.dart';
|
||||||
@ -118,10 +117,6 @@ class AppRouter extends _$AppRouter {
|
|||||||
guards: [_authGuard, _duplicateGuard],
|
guards: [_authGuard, _duplicateGuard],
|
||||||
transitionsBuilder: CustomTransitionsBuilders.zoomedPage,
|
transitionsBuilder: CustomTransitionsBuilders.zoomedPage,
|
||||||
),
|
),
|
||||||
AutoRoute(
|
|
||||||
page: VideoViewerRoute.page,
|
|
||||||
guards: [_authGuard, _duplicateGuard],
|
|
||||||
),
|
|
||||||
AutoRoute(
|
AutoRoute(
|
||||||
page: BackupControllerRoute.page,
|
page: BackupControllerRoute.page,
|
||||||
guards: [_authGuard, _duplicateGuard, _backupPermissionGuard],
|
guards: [_authGuard, _duplicateGuard, _backupPermissionGuard],
|
||||||
|
@ -351,21 +351,6 @@ abstract class _$AppRouter extends RootStackRouter {
|
|||||||
child: const TrashPage(),
|
child: const TrashPage(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
VideoViewerRoute.name: (routeData) {
|
|
||||||
final args = routeData.argsAs<VideoViewerRouteArgs>();
|
|
||||||
return AutoRoutePage<dynamic>(
|
|
||||||
routeData: routeData,
|
|
||||||
child: VideoViewerPage(
|
|
||||||
key: args.key,
|
|
||||||
asset: args.asset,
|
|
||||||
isMotionVideo: args.isMotionVideo,
|
|
||||||
placeholder: args.placeholder,
|
|
||||||
showControls: args.showControls,
|
|
||||||
hideControlsTimer: args.hideControlsTimer,
|
|
||||||
showDownloadingIndicator: args.showDownloadingIndicator,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1410,66 +1395,3 @@ class TrashRoute extends PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const PageInfo<void> page = PageInfo<void>(name);
|
static const PageInfo<void> page = PageInfo<void>(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
|
||||||
/// [VideoViewerPage]
|
|
||||||
class VideoViewerRoute extends PageRouteInfo<VideoViewerRouteArgs> {
|
|
||||||
VideoViewerRoute({
|
|
||||||
Key? key,
|
|
||||||
required Asset asset,
|
|
||||||
bool isMotionVideo = false,
|
|
||||||
Widget? placeholder,
|
|
||||||
bool showControls = true,
|
|
||||||
Duration hideControlsTimer = const Duration(seconds: 5),
|
|
||||||
bool showDownloadingIndicator = true,
|
|
||||||
List<PageRouteInfo>? children,
|
|
||||||
}) : super(
|
|
||||||
VideoViewerRoute.name,
|
|
||||||
args: VideoViewerRouteArgs(
|
|
||||||
key: key,
|
|
||||||
asset: asset,
|
|
||||||
isMotionVideo: isMotionVideo,
|
|
||||||
placeholder: placeholder,
|
|
||||||
showControls: showControls,
|
|
||||||
hideControlsTimer: hideControlsTimer,
|
|
||||||
showDownloadingIndicator: showDownloadingIndicator,
|
|
||||||
),
|
|
||||||
initialChildren: children,
|
|
||||||
);
|
|
||||||
|
|
||||||
static const String name = 'VideoViewerRoute';
|
|
||||||
|
|
||||||
static const PageInfo<VideoViewerRouteArgs> page =
|
|
||||||
PageInfo<VideoViewerRouteArgs>(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
class VideoViewerRouteArgs {
|
|
||||||
const VideoViewerRouteArgs({
|
|
||||||
this.key,
|
|
||||||
required this.asset,
|
|
||||||
this.isMotionVideo = false,
|
|
||||||
this.placeholder,
|
|
||||||
this.showControls = true,
|
|
||||||
this.hideControlsTimer = const Duration(seconds: 5),
|
|
||||||
this.showDownloadingIndicator = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Key? key;
|
|
||||||
|
|
||||||
final Asset asset;
|
|
||||||
|
|
||||||
final bool isMotionVideo;
|
|
||||||
|
|
||||||
final Widget? placeholder;
|
|
||||||
|
|
||||||
final bool showControls;
|
|
||||||
|
|
||||||
final Duration hideControlsTimer;
|
|
||||||
|
|
||||||
final bool showDownloadingIndicator;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'VideoViewerRouteArgs{key: $key, asset: $asset, isMotionVideo: $isMotionVideo, placeholder: $placeholder, showControls: $showControls, hideControlsTimer: $hideControlsTimer, showDownloadingIndicator: $showDownloadingIndicator}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -79,7 +79,7 @@ class _LocationPicker extends HookWidget {
|
|||||||
).tr(),
|
).tr(),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.popRoute(latlng),
|
onPressed: () => context.maybePop(latlng),
|
||||||
child: Text(
|
child: Text(
|
||||||
"action_common_update",
|
"action_common_update",
|
||||||
style: context.textTheme.bodyMedium?.copyWith(
|
style: context.textTheme.bodyMedium?.copyWith(
|
||||||
|
@ -105,7 +105,7 @@ class AppLogPage extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.popRoute();
|
context.maybePop();
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_back_ios_new_rounded,
|
Icons.arrow_back_ios_new_rounded,
|
||||||
|
@ -61,18 +61,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: auto_route
|
name: auto_route
|
||||||
sha256: "82f8df1d177416bc6b7a449127d0270ff1f0f633a91f2ceb7a85d4f07c3affa1"
|
sha256: f04022b2a5c4d255f7feb139a75cb3d100ccd2f8918a75036fe09456309a13a3
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.8.4"
|
version: "8.0.3"
|
||||||
auto_route_generator:
|
auto_route_generator:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: auto_route_generator
|
name: auto_route_generator
|
||||||
sha256: "11067a3bcd643812518fe26c0c9ec073990286cabfd9d74b6da9ef9b913c4d22"
|
sha256: ba28133d3a3bf0a66772bcc98dade5843753cd9f1a8fb4802b842895515b67d3
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.3.2"
|
version: "8.0.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1804,5 +1804,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.2.0 <4.0.0"
|
dart: ">=3.3.0 <4.0.0"
|
||||||
flutter: ">=3.16.0"
|
flutter: ">=3.16.0"
|
||||||
|
@ -5,7 +5,7 @@ publish_to: 'none'
|
|||||||
version: 1.101.0+131
|
version: 1.101.0+131
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
@ -21,7 +21,7 @@ dependencies:
|
|||||||
cached_network_image: ^3.3.1
|
cached_network_image: ^3.3.1
|
||||||
flutter_cache_manager: ^3.3.1
|
flutter_cache_manager: ^3.3.1
|
||||||
intl: ^0.18.0
|
intl: ^0.18.0
|
||||||
auto_route: ^7.8.4
|
auto_route: ^8.0.2
|
||||||
fluttertoast: ^8.2.4
|
fluttertoast: ^8.2.4
|
||||||
video_player: ^2.8.2
|
video_player: ^2.8.2
|
||||||
chewie: ^1.7.4
|
chewie: ^1.7.4
|
||||||
@ -87,7 +87,7 @@ dev_dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^3.0.1
|
flutter_lints: ^3.0.1
|
||||||
build_runner: ^2.4.8
|
build_runner: ^2.4.8
|
||||||
auto_route_generator: ^7.3.2
|
auto_route_generator: ^8.0.0
|
||||||
flutter_launcher_icons: ^0.13.1
|
flutter_launcher_icons: ^0.13.1
|
||||||
flutter_native_splash: ^2.3.9
|
flutter_native_splash: ^2.3.9
|
||||||
isar_generator: ^3.1.0+1
|
isar_generator: ^3.1.0+1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user