Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mobile): Auto switching server URLs #14437

Merged
merged 40 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c911211
feat: new settings card
alextran1502 Nov 23, 2024
4fbc146
Add networking settings
alextran1502 Nov 23, 2024
6acd215
wip
alextran1502 Nov 24, 2024
b0d34db
Merge branch 'main' of github.com:immich-app/immich into networking-s…
alextran1502 Nov 26, 2024
ff4db18
Merge branch 'main' of github.com:immich-app/immich into networking-s…
alextran1502 Nov 26, 2024
f1a99c8
feat: add correct permission to get WIFI name
alextran1502 Nov 27, 2024
59ca288
feat: validate aux endpoint
alextran1502 Nov 27, 2024
fc9dd6d
feat: validation on the go
alextran1502 Nov 27, 2024
6fb346e
reordering
alextran1502 Nov 27, 2024
0366b78
feat: new card UI
alextran1502 Nov 27, 2024
2db7942
new style
alextran1502 Nov 28, 2024
4cb8351
feat: enable switch
alextran1502 Nov 28, 2024
adbe438
refactor
alextran1502 Nov 28, 2024
4eaa8ca
visual for when the feature is disabled
alextran1502 Nov 28, 2024
6c4eb59
update
alextran1502 Nov 29, 2024
6ad6052
Save local connection info
alextran1502 Nov 30, 2024
4b80524
feat: auto switching endpoint on app resumed
alextran1502 Nov 30, 2024
22f1a61
feat: auto switch endpoint when app restart, handling endpoint offline
alextran1502 Dec 1, 2024
6c3d1c3
chore: clean up
alextran1502 Dec 1, 2024
15e5572
linting
alextran1502 Dec 1, 2024
f780548
pr feedback
alextran1502 Dec 2, 2024
01c2cc0
update rules
alextran1502 Dec 2, 2024
35b4296
Merge branch 'main' of github.com:immich-app/immich into networking-s…
alextran1502 Dec 2, 2024
ca94cd6
chore: translations strings
alextran1502 Dec 2, 2024
58a6ca6
remove toast message when switching endpoint
alextran1502 Dec 2, 2024
72ba8ac
log connection info instead
alextran1502 Dec 2, 2024
95f87a5
adding tests
alextran1502 Dec 2, 2024
a84f35a
Add more tests
alextran1502 Dec 2, 2024
32e1e88
Linting
alextran1502 Dec 2, 2024
04feb33
Background upload: android
alextran1502 Dec 3, 2024
9fa8972
Background upload: android
alextran1502 Dec 3, 2024
a352d8e
Background upload: ios wip
alextran1502 Dec 3, 2024
82432d3
Background upload: ios
alextran1502 Dec 4, 2024
dc9047e
permission request and clean up
alextran1502 Dec 4, 2024
a596198
chore: remove saved info on signout
alextran1502 Dec 4, 2024
23e6c24
merge main
alextran1502 Dec 4, 2024
900da27
merge main
alextran1502 Dec 4, 2024
c77ccc5
pr feedback
alextran1502 Dec 5, 2024
93e086f
lint
alextran1502 Dec 5, 2024
55f437a
pr feedback
alextran1502 Dec 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mobile/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ custom_lint:
- lib/widgets/album/album_thumbnail_listtile.dart
- lib/widgets/forms/login/login_form.dart
- lib/widgets/search/search_filter/{camera_picker,location_picker,people_picker}.dart
- lib/services/auth.service.dart # on ApiException
- test/services/auth.service_test.dart # on ApiException

dart_code_metrics:
metrics:
Expand Down
2 changes: 2 additions & 0 deletions mobile/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<!-- Foreground service permission -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Expand Down
38 changes: 33 additions & 5 deletions mobile/assets/i18n/en-US.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,35 @@
{
"location_permission": "Location permission",
"location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name",
"background_location_permission": "Background location permission",
"background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name",
"current_server_address": "Current server address",
"grant_permission": "Grant permission",
"automatic_endpoint_switching_title": "Automatic URL switching",
"automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere",
"local_network": "Local network",
"local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network",
"external_network": "External network",
"external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom",
"networking_settings": "Networking",
"networking_subtitle": "Manage the server endpoint settings",
"cancel": "Cancel",
"save": "Save",
"wifi_name": "WiFi Name",
"enter_wifi_name": "Enter WiFi name",
"your_wifi_name": "Your WiFi name",
"server_endpoint": "Server Endpoint",
"get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network",
"use_current_connection": "use current connection",
"add_endpoint": "Add endpoint",
"validate_endpoint_error": "Please enter a valid URL",
"advanced_settings_tile_subtitle": "Manage advanced settings",
"asset_viewer_settings_subtitle": "Manage your gallery viewer settings",
"backup_setting_subtitle": "Manage background and foreground upload settings",
"setting_languages_subtitle": "Change the app's language",
"setting_notifications_subtitle": "Manage your notification settings",
"preferences_settings_subtitle": "Manage the app's preferences",
"asset_list_settings_subtitle": "Manage the look of the timeline",
"action_common_back": "Back",
"action_common_cancel": "Cancel",
"action_common_clear": "Clear",
Expand All @@ -16,7 +47,6 @@
"advanced_settings_proxy_headers_title": "Proxy Headers",
"advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.",
"advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates",
"advanced_settings_tile_subtitle": "Advanced user's settings",
"advanced_settings_tile_title": "Advanced",
"advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting",
"advanced_settings_troubleshooting_title": "Troubleshooting",
Expand Down Expand Up @@ -56,7 +86,6 @@
"asset_list_layout_settings_group_by_month": "Month",
"asset_list_layout_settings_group_by_month_day": "Month + day",
"asset_list_layout_sub_title": "Layout",
"asset_list_settings_subtitle": "Photo grid layout settings",
"asset_list_settings_title": "Photo Grid",
"asset_restored_successfully": "Asset restored successfully",
"assets_deleted_permanently": "{} asset(s) deleted permanently",
Expand All @@ -65,7 +94,7 @@
"assets_restored_successfully": "{} asset(s) restored successfully",
"assets_trashed": "{} asset(s) trashed",
"assets_trashed_from_server": "{} asset(s) trashed from the Immich server",
"asset_viewer_settings_title": "Asset Viewer",
"asset_viewer_settings_title": "Gallery Viewer",
"backup_album_selection_page_albums_device": "Albums on device ({})",
"backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude",
"backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.",
Expand Down Expand Up @@ -492,7 +521,6 @@
"setting_notifications_notify_seconds": "{} seconds",
"setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset",
"setting_notifications_single_progress_title": "Show background backup detail progress",
"setting_notifications_subtitle": "Adjust your notification preferences",
"setting_notifications_title": "Notifications",
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
"setting_notifications_total_progress_title": "Show background backup total progress",
Expand Down Expand Up @@ -625,4 +653,4 @@
"viewer_remove_from_stack": "Remove from Stack",
"viewer_stack_use_as_main_asset": "Use as Main Asset",
"viewer_unstack": "Un-Stack"
}
}
7 changes: 7 additions & 0 deletions mobile/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ post_install do |installer|

## dart: PermissionGroup.criticalAlerts
# 'PERMISSION_CRITICAL_ALERTS=1'

## The 'PERMISSION_LOCATION' macro enables the `locationWhenInUse` and `locationAlways` permission. If
## the application only requires `locationWhenInUse`, only specify the `PERMISSION_LOCATION_WHENINUSE`
## macro.
##
## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
'PERMISSION_LOCATION=1',
]

end
Expand Down
8 changes: 7 additions & 1 deletion mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ PODS:
- MapLibre (= 5.14.0-pre3)
- native_video_player (1.0.0):
- Flutter
- network_info_plus (0.0.1):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
Expand Down Expand Up @@ -115,6 +117,7 @@ DEPENDENCIES:
- isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`)
- maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`)
- native_video_player (from `.symlinks/plugins/native_video_player/ios`)
- network_info_plus (from `.symlinks/plugins/network_info_plus/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
Expand Down Expand Up @@ -169,6 +172,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/maplibre_gl/ios"
native_video_player:
:path: ".symlinks/plugins/native_video_player/ios"
network_info_plus:
:path: ".symlinks/plugins/network_info_plus/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
Expand Down Expand Up @@ -210,6 +215,7 @@ SPEC CHECKSUMS:
MapLibre: 620fc933c1d6029b33738c905c1490d024e5d4ef
maplibre_gl: a2efec727dd340e4c65e26d2b03b584f14881fd9
native_video_player: d12af78a1a4a8cf09775a5177d5b392def6fd23c
network_info_plus: 6613d9d7cdeb0e6f366ed4dbe4b3c51c52d567a9
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
Expand All @@ -225,6 +231,6 @@ SPEC CHECKSUMS:
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1

PODFILE CHECKSUM: 64c9b5291666c0ca3caabdfe9865c141ac40321d
PODFILE CHECKSUM: 2282844f7aed70427ae663932332dad1225156c8

COCOAPODS: 1.15.2
6 changes: 5 additions & 1 deletion mobile/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E0E99CDC17B3EB7FA8BA2332 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
F7101BB0391A314774615E89 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
FA9973382CF6DF4B000EF859 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerProfile.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -126,6 +127,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
FA9973382CF6DF4B000EF859 /* Runner.entitlements */,
65DD438629917FAD0047FFA8 /* BackgroundSync */,
FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
Expand Down Expand Up @@ -541,6 +543,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 184;
Expand All @@ -553,7 +556,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.121.0;
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.debug;
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug;
PRODUCT_NAME = "Immich-Debug";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand All @@ -569,6 +572,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 184;
Expand Down
22 changes: 10 additions & 12 deletions mobile/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import BackgroundTasks
import Flutter
import UIKit
import network_info_plus
import path_provider_ios
import permission_handler_apple
import photo_manager
import shared_preferences_foundation
import UIKit

@main
@objc class AppDelegate: FlutterAppDelegate {

override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {

// Required for flutter_local_notification
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
Expand All @@ -33,27 +32,26 @@ import shared_preferences_foundation

BackgroundServicePlugin.setPluginRegistrantCallback { registry in
if !registry.hasPlugin("org.cocoapods.path-provider-ios") {
FLTPathProviderPlugin.register(
with: registry.registrar(forPlugin: "org.cocoapods.path-provider-ios")!)
FLTPathProviderPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.path-provider-ios")!)
}

if !registry.hasPlugin("org.cocoapods.photo-manager") {
PhotoManagerPlugin.register(
with: registry.registrar(forPlugin: "org.cocoapods.photo-manager")!)
PhotoManagerPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.photo-manager")!)
}

if !registry.hasPlugin("org.cocoapods.shared-preferences-foundation") {
SharedPreferencesPlugin.register(
with: registry.registrar(forPlugin: "org.cocoapods.shared-preferences-foundation")!)
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.shared-preferences-foundation")!)
}

if !registry.hasPlugin("org.cocoapods.permission-handler-apple") {
PermissionHandlerPlugin.register(
with: registry.registrar(forPlugin: "org.cocoapods.permission-handler-apple")!)
PermissionHandlerPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.permission-handler-apple")!)
}

if !registry.hasPlugin("org.cocoapods.network-info-plus") {
FPPNetworkInfoPlusPlugin.register(with: registry.registrar(forPlugin: "org.cocoapods.network-info-plus")!)
}
}

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

}
6 changes: 5 additions & 1 deletion mobile/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,12 @@
</dict>
<key>NSCameraUsageDescription</key>
<string>We need to access the camera to let you take beautiful video using this app</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We require this permission to access the local WiFi name for background upload mechanism</string>
<key>NSLocationUsageDescription</key>
<string>We require this permission to access the local WiFi name</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Enable location setting to show position of assets on map</string>
<string>We require this permission to access the local WiFi name</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need to access the microphone to let you take beautiful video using this app</string>
<key>NSPhotoLibraryAddUsageDescription</key>
Expand Down
5 changes: 4 additions & 1 deletion mobile/ios/Runner/Runner.entitlements
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
<dict>
<key>com.apple.developer.networking.wifi-info</key>
<true/>
</dict>
</plist>
2 changes: 2 additions & 0 deletions mobile/ios/Runner/RunnerProfile.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.networking.wifi-info</key>
<true/>
</dict>
</plist>
6 changes: 6 additions & 0 deletions mobile/lib/entities/store.entity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ enum StoreKey<T> {
colorfulInterface<bool>(130, type: bool),

syncAlbums<bool>(131, type: bool),

// Auto endpoint switching
autoEndpointSwitching<bool>(132, type: bool),
preferredWifiName<String>(133, type: String),
localEndpoint<String>(134, type: String),
externalEndpointList<String>(135, type: String),
;

const StoreKey(
Expand Down
4 changes: 4 additions & 0 deletions mobile/lib/extensions/build_context_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ extension ContextHelper on BuildContext {

// Managing focus within the widget tree from the current context
FocusScopeNode get focusScope => FocusScope.of(this);

// Show SnackBars from the current context
void showSnackBar(SnackBar snackBar) =>
ScaffoldMessenger.of(this).showSnackBar(snackBar);
}
6 changes: 6 additions & 0 deletions mobile/lib/interfaces/auth.interface.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import 'package:immich_mobile/interfaces/database.interface.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';

abstract interface class IAuthRepository implements IDatabaseRepository {
Future<void> clearLocalData();
String getAccessToken();
bool getEndpointSwitchingFeature();
String? getPreferredWifiName();
String? getLocalEndpoint();
List<AuxilaryEndpoint> getExternalEndpointList();
}
4 changes: 4 additions & 0 deletions mobile/lib/interfaces/network.interface.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
abstract interface class INetworkRepository {
Future<String?> getWifiName();
Future<String?> getWifiIp();
}
Loading
Loading