diff --git a/lib/apis/auth_info_api.dart b/lib/apis/auth_info_api.dart index d1a8a18..263c9f2 100644 --- a/lib/apis/auth_info_api.dart +++ b/lib/apis/auth_info_api.dart @@ -1,12 +1,12 @@ import 'dart:convert'; import 'package:open_media_server_app/apis/base_api.dart'; import 'package:http/http.dart' as http; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/preference_globals.dart'; import 'package:open_media_server_app/models/auth/auth_info.dart'; class AuthInfoApi { Future getAuthInfo() async { - String apiUrl = "${Globals.BaseUrl}/auth/info"; + String apiUrl = "${PreferenceGlobals.BaseUrl}/auth/info"; var headers = BaseApi.getHeaders(); diff --git a/lib/apis/base_api.dart b/lib/apis/base_api.dart index a8b5f56..6ed25c5 100644 --- a/lib/apis/base_api.dart +++ b/lib/apis/base_api.dart @@ -1,4 +1,4 @@ -import 'package:open_media_server_app/helpers/Preferences.dart'; +import 'package:open_media_server_app/helpers/preferences.dart'; class BaseApi { static Map getHeaders() { diff --git a/lib/apis/inventory_api.dart b/lib/apis/inventory_api.dart index 4d71d02..8e649e4 100644 --- a/lib/apis/inventory_api.dart +++ b/lib/apis/inventory_api.dart @@ -1,6 +1,6 @@ import 'dart:convert'; import 'package:open_media_server_app/apis/base_api.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/preference_globals.dart'; import 'package:open_media_server_app/models/inventory/episode.dart'; import 'package:open_media_server_app/models/inventory/inventory_item.dart'; import 'package:http/http.dart' as http; @@ -10,7 +10,7 @@ import 'package:open_media_server_app/models/inventory/show.dart'; class InventoryApi { Future> listItems(String category) async { - String apiUrl = "${Globals.BaseUrl}/api/inventory/items?"; + String apiUrl = "${PreferenceGlobals.BaseUrl}/api/inventory/items?"; var headers = BaseApi.getHeaders(); @@ -26,7 +26,7 @@ class InventoryApi { } Future getMovie(String id) async { - String apiUrl = "${Globals.BaseUrl}/api/inventory/movie?"; + String apiUrl = "${PreferenceGlobals.BaseUrl}/api/inventory/movie?"; var headers = BaseApi.getHeaders(); @@ -42,7 +42,7 @@ class InventoryApi { } Future getShow(String id) async { - String apiUrl = "${Globals.BaseUrl}/api/inventory/show?"; + String apiUrl = "${PreferenceGlobals.BaseUrl}/api/inventory/show?"; var headers = BaseApi.getHeaders(); @@ -58,7 +58,7 @@ class InventoryApi { } Future getSeason(String id) async { - String apiUrl = "${Globals.BaseUrl}/api/inventory/season?"; + String apiUrl = "${PreferenceGlobals.BaseUrl}/api/inventory/season?"; var headers = BaseApi.getHeaders(); @@ -74,7 +74,7 @@ class InventoryApi { } Future getEpisode(String id) async { - String apiUrl = "${Globals.BaseUrl}/api/inventory/episode?"; + String apiUrl = "${PreferenceGlobals.BaseUrl}/api/inventory/episode?"; var headers = BaseApi.getHeaders(); diff --git a/lib/apis/metadata_api.dart b/lib/apis/metadata_api.dart index 7c3a5c8..9cf3e2b 100644 --- a/lib/apis/metadata_api.dart +++ b/lib/apis/metadata_api.dart @@ -1,12 +1,12 @@ import 'dart:convert'; import 'package:open_media_server_app/apis/base_api.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/preference_globals.dart'; import 'package:open_media_server_app/models/metadata/metadata_model.dart'; import 'package:http/http.dart' as http; class MetadataApi { Future getMetadata(String id, String category) async { - String apiUrl = "${Globals.BaseUrl}/api/metadata?"; + String apiUrl = "${PreferenceGlobals.BaseUrl}/api/metadata?"; var headers = BaseApi.getHeaders(); diff --git a/lib/auth/login_manager.dart b/lib/auth/login_manager.dart index ce793d4..096a218 100644 --- a/lib/auth/login_manager.dart +++ b/lib/auth/login_manager.dart @@ -1,4 +1,4 @@ -import 'package:open_media_server_app/auth/auth_globals.dart'; +import 'package:open_media_server_app/globals/auth_globals.dart'; import 'package:open_media_server_app/auth/oauth_handler/custom_web_base_dummy.dart' if (dart.library.html) './oauth_handler/custom_web_base.dart'; import 'package:flutter/foundation.dart'; @@ -7,8 +7,9 @@ import 'package:oauth2_client/access_token_response.dart'; import 'package:oauth2_client/interfaces.dart'; import 'package:oauth2_client/oauth2_client.dart'; import 'package:open_media_server_app/auth/device_code.dart'; -import 'package:open_media_server_app/globals.dart'; -import 'package:open_media_server_app/helpers/Preferences.dart'; +import 'package:open_media_server_app/globals/globals.dart'; +import 'package:open_media_server_app/globals/platform_globals.dart'; +import 'package:open_media_server_app/helpers/preferences.dart'; import 'package:open_media_server_app/models/auth/auth_info.dart'; import 'package:random_string/random_string.dart'; @@ -18,16 +19,16 @@ class LoginManager { BaseWebAuth? baseWebAuth; LoginManager(AuthInfo authInfo) { - if (Globals.isTv) { + if (PlatformGlobals.isTv) { // Do nothing - } else if (!Globals.isWeb) { + } else if (!PlatformGlobals.isWeb) { client = OAuth2Client( authorizeUrl: authInfo.authorizeUrl, tokenUrl: authInfo.tokenUrl, redirectUri: "my.test.app:/oauth2redirect", // TODO customUriScheme: "my.test.app", ); - } else if (Globals.isWeb) { + } else if (PlatformGlobals.isWeb) { client = OAuth2Client( authorizeUrl: authInfo.authorizeUrl, tokenUrl: authInfo.tokenUrl, @@ -43,7 +44,7 @@ class LoginManager { } Future login(AuthInfo authInfo, BuildContext context) async { - if (Globals.isTv) { + if (PlatformGlobals.isTv) { DeviceCode deviceCode = DeviceCode(); var token = await deviceCode.authenticateUser( authInfo, "offline_access", authInfo.deviceCodeUrl, context); diff --git a/lib/auth/oauth_handler/custom_web_base.dart b/lib/auth/oauth_handler/custom_web_base.dart index c73d5a4..12d006f 100644 --- a/lib/auth/oauth_handler/custom_web_base.dart +++ b/lib/auth/oauth_handler/custom_web_base.dart @@ -1,9 +1,9 @@ import 'package:oauth2_client/interfaces.dart'; -import 'package:open_media_server_app/auth/auth_globals.dart'; +import 'package:open_media_server_app/globals/auth_globals.dart'; // ignore: avoid_web_libraries_in_flutter import 'dart:html' as html; -import 'package:open_media_server_app/helpers/Preferences.dart'; +import 'package:open_media_server_app/helpers/preferences.dart'; class CustomWebBase implements BaseWebAuth { @override diff --git a/lib/auth/auth_globals.dart b/lib/globals/auth_globals.dart similarity index 62% rename from lib/auth/auth_globals.dart rename to lib/globals/auth_globals.dart index 9e9e7e5..8ca32f2 100644 --- a/lib/auth/auth_globals.dart +++ b/lib/globals/auth_globals.dart @@ -1,13 +1,15 @@ import 'package:flutter/foundation.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/preference_globals.dart'; class AuthGlobals { static String get redirectUriWeb { if (kDebugMode) { return "http://localhost:8000/redirect.html"; } else { - return "https://${Globals.BaseUrl}/redirect.html"; + return "https://${PreferenceGlobals.BaseUrl}/redirect.html"; } } + static String? appLoginCodeRoute; + } \ No newline at end of file diff --git a/lib/globals.dart b/lib/globals/globals.dart similarity index 55% rename from lib/globals.dart rename to lib/globals/globals.dart index 9faeed1..ac26063 100644 --- a/lib/globals.dart +++ b/lib/globals/globals.dart @@ -1,12 +1,5 @@ class Globals { - static String BaseUrl = "http://localhost:8080"; - static String Title = "Open Media Station"; static String PictureNotFoundUrl = "https://static.vecteezy.com/system/resources/previews/005/337/799/original/icon-image-not-found-free-vector.jpg"; - - static bool isTv = false; - static bool isAndroidTv = false; - static bool isMobile = false; - static bool isWeb = false; } diff --git a/lib/globals/platform_globals.dart b/lib/globals/platform_globals.dart new file mode 100644 index 0000000..f777b4b --- /dev/null +++ b/lib/globals/platform_globals.dart @@ -0,0 +1,34 @@ +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; + +class PlatformGlobals { + static bool isTv = false; + static bool isAndroidTv = false; + static bool isMobile = false; + static bool isWeb = false; + + static Future setGlobals() async { + PlatformGlobals.isMobile = defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.android; + + if (defaultTargetPlatform == TargetPlatform.android) { + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + PlatformGlobals.isTv = + androidInfo.systemFeatures.contains('android.software.leanback'); + } + + if (PlatformGlobals.isTv) { + PlatformGlobals.isMobile = false; + } + + if (PlatformGlobals.isTv && + defaultTargetPlatform == TargetPlatform.android) { + PlatformGlobals.isAndroidTv = true; + } + + if (kIsWeb) { + PlatformGlobals.isWeb = true; + } + } +} diff --git a/lib/globals/preference_globals.dart b/lib/globals/preference_globals.dart new file mode 100644 index 0000000..71b51cb --- /dev/null +++ b/lib/globals/preference_globals.dart @@ -0,0 +1,5 @@ +import 'package:open_media_server_app/helpers/preferences.dart'; + +class PreferenceGlobals { + static String BaseUrl = Preferences.prefs!.getString("BaseUrl")!; +} \ No newline at end of file diff --git a/lib/helpers/Preferences.dart b/lib/helpers/preferences.dart similarity index 100% rename from lib/helpers/Preferences.dart rename to lib/helpers/preferences.dart diff --git a/lib/main.dart b/lib/main.dart index 0036350..f728fe7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,39 +1,18 @@ -import 'package:device_info_plus/device_info_plus.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:media_kit/media_kit.dart'; -import 'package:open_media_server_app/apis/auth_info_api.dart'; -import 'package:open_media_server_app/auth/auth_globals.dart'; -import 'package:open_media_server_app/auth/login_manager.dart'; -import 'package:open_media_server_app/gallery.dart'; -import 'package:open_media_server_app/globals.dart'; -import 'package:open_media_server_app/helpers/Preferences.dart'; +import 'package:open_media_server_app/globals/auth_globals.dart'; +import 'package:open_media_server_app/globals/platform_globals.dart'; +import 'package:open_media_server_app/views/gallery.dart'; +import 'package:open_media_server_app/globals/globals.dart'; +import 'package:open_media_server_app/helpers/preferences.dart'; +import 'package:open_media_server_app/views/login.dart'; import 'package:shared_preferences/shared_preferences.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); MediaKit.ensureInitialized(); - Globals.isMobile = defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.android; - if (defaultTargetPlatform == TargetPlatform.android) { - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - Globals.isTv = - androidInfo.systemFeatures.contains('android.software.leanback'); - } - - if (Globals.isTv) { - Globals.isMobile = false; - } - - if (Globals.isTv && defaultTargetPlatform == TargetPlatform.android) { - Globals.isAndroidTv = true; - } - - if (kIsWeb) { - Globals.isWeb = true; - } + await PlatformGlobals.setGlobals(); var prefs = await SharedPreferences.getInstance(); Preferences.prefs = prefs; @@ -48,6 +27,7 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( onGenerateRoute: (settings) { + // For authentication in web if (settings.name?.contains("code") ?? false) { AuthGlobals.appLoginCodeRoute = settings.name; } @@ -62,45 +42,7 @@ class MyApp extends StatelessWidget { ), useMaterial3: true, ), - home: HomePage(title: Globals.Title), - ); - } -} - -class HomePage extends StatelessWidget { - const HomePage({super.key, required this.title}); - - final String title; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - surfaceTintColor: Colors.transparent, - title: Text(title), - ), - body: FutureBuilder( - future: authenticate(context), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text('Error: ${snapshot.error}')); - } - - return const Gallery(); - }, - ), + home: const LoginView(widget: Gallery()), ); } - - Future authenticate(BuildContext context) async { - AuthInfoApi authInfoApi = AuthInfoApi(); - var info = await authInfoApi.getAuthInfo(); - - LoginManager loginManager = LoginManager(info); - - var token = await loginManager.login(info, context); - } } diff --git a/lib/views/episode_detail.dart b/lib/views/detail_views/episode_detail.dart similarity index 91% rename from lib/views/episode_detail.dart rename to lib/views/detail_views/episode_detail.dart index 1c9fdc8..2302e39 100644 --- a/lib/views/episode_detail.dart +++ b/lib/views/detail_views/episode_detail.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/globals.dart'; +import 'package:open_media_server_app/globals/preference_globals.dart'; import 'package:open_media_server_app/models/internal/grid_item_model.dart'; -import 'package:open_media_server_app/player.dart'; +import 'package:open_media_server_app/views/player.dart'; import 'package:open_media_server_app/widgets/custom_image.dart'; class EpisodeDetailView extends StatelessWidget { @@ -71,7 +72,7 @@ class EpisodeDetailView extends StatelessWidget { MaterialPageRoute( builder: (context) => PlayerView( url: - "${Globals.BaseUrl}/stream/${itemModel.inventoryItem?.category}/${itemModel.inventoryItem?.id}"), + "${PreferenceGlobals.BaseUrl}/stream/${itemModel.inventoryItem?.category}/${itemModel.inventoryItem?.id}"), ), ); }, diff --git a/lib/views/movie_detail.dart b/lib/views/detail_views/movie_detail.dart similarity index 91% rename from lib/views/movie_detail.dart rename to lib/views/detail_views/movie_detail.dart index ea75340..6101047 100644 --- a/lib/views/movie_detail.dart +++ b/lib/views/detail_views/movie_detail.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/globals.dart'; +import 'package:open_media_server_app/globals/preference_globals.dart'; import 'package:open_media_server_app/models/internal/grid_item_model.dart'; -import 'package:open_media_server_app/player.dart'; +import 'package:open_media_server_app/views/player.dart'; import 'package:open_media_server_app/widgets/custom_image.dart'; class MovieDetailView extends StatelessWidget { @@ -70,7 +71,7 @@ class MovieDetailView extends StatelessWidget { MaterialPageRoute( builder: (context) => PlayerView( url: - "${Globals.BaseUrl}/stream/${itemModel.inventoryItem?.category}/${itemModel.inventoryItem?.id}"), + "${PreferenceGlobals.BaseUrl}/stream/${itemModel.inventoryItem?.category}/${itemModel.inventoryItem?.id}"), ), ); }, diff --git a/lib/views/season_detail.dart b/lib/views/detail_views/season_detail.dart similarity index 98% rename from lib/views/season_detail.dart rename to lib/views/detail_views/season_detail.dart index 0903e19..334137b 100644 --- a/lib/views/season_detail.dart +++ b/lib/views/detail_views/season_detail.dart @@ -3,10 +3,10 @@ import 'package:flutter/material.dart'; import 'package:open_media_server_app/apis/base_api.dart'; import 'package:open_media_server_app/apis/inventory_api.dart'; import 'package:open_media_server_app/apis/metadata_api.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/globals.dart'; import 'package:open_media_server_app/models/internal/grid_item_model.dart'; import 'package:open_media_server_app/models/metadata/metadata_model.dart'; -import 'package:open_media_server_app/views/episode_detail.dart'; +import 'package:open_media_server_app/views/detail_views/episode_detail.dart'; import 'package:open_media_server_app/widgets/custom_image.dart'; import 'package:open_media_server_app/widgets/title.dart'; diff --git a/lib/views/show_detail.dart b/lib/views/detail_views/show_detail.dart similarity index 97% rename from lib/views/show_detail.dart rename to lib/views/detail_views/show_detail.dart index b09eead..2d6b2d2 100644 --- a/lib/views/show_detail.dart +++ b/lib/views/detail_views/show_detail.dart @@ -3,10 +3,10 @@ import 'package:flutter/material.dart'; import 'package:open_media_server_app/apis/base_api.dart'; import 'package:open_media_server_app/apis/inventory_api.dart'; import 'package:open_media_server_app/apis/metadata_api.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/globals.dart'; import 'package:open_media_server_app/models/internal/grid_item_model.dart'; import 'package:open_media_server_app/models/metadata/metadata_model.dart'; -import 'package:open_media_server_app/views/season_detail.dart'; +import 'package:open_media_server_app/views/detail_views/season_detail.dart'; import 'package:open_media_server_app/widgets/custom_image.dart'; import 'package:open_media_server_app/widgets/title.dart'; diff --git a/lib/gallery.dart b/lib/views/gallery.dart similarity index 92% rename from lib/gallery.dart rename to lib/views/gallery.dart index 6e996a2..f40c04f 100644 --- a/lib/gallery.dart +++ b/lib/views/gallery.dart @@ -1,13 +1,13 @@ import 'package:flutter/material.dart'; import 'package:open_media_server_app/apis/inventory_api.dart'; import 'package:open_media_server_app/apis/metadata_api.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/globals.dart'; import 'package:open_media_server_app/models/internal/grid_item_model.dart'; import 'package:open_media_server_app/models/metadata/metadata_model.dart'; -import 'package:open_media_server_app/gallery_item.dart'; -import 'package:open_media_server_app/views/movie_detail.dart'; -import 'package:open_media_server_app/player.dart'; -import 'package:open_media_server_app/views/show_detail.dart'; +import 'package:open_media_server_app/widgets/gallery_item.dart'; +import 'package:open_media_server_app/views/detail_views/movie_detail.dart'; +import 'package:open_media_server_app/views/player.dart'; +import 'package:open_media_server_app/views/detail_views/show_detail.dart'; class Gallery extends StatelessWidget { const Gallery({Key? key}) : super(key: key); diff --git a/lib/views/login.dart b/lib/views/login.dart new file mode 100644 index 0000000..4661a64 --- /dev/null +++ b/lib/views/login.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:open_media_server_app/apis/auth_info_api.dart'; +import 'package:open_media_server_app/auth/login_manager.dart'; +import 'package:open_media_server_app/globals/globals.dart'; +import 'package:open_media_server_app/helpers/preferences.dart'; + +class LoginView extends StatelessWidget { + const LoginView({super.key, required this.widget}); + + final Widget widget; + + @override + Widget build(BuildContext context) { + Preferences.prefs!.setString("BaseUrl", ""); + + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + surfaceTintColor: Colors.transparent, + title: Text(Globals.Title), + ), + body: FutureBuilder( + future: authenticate(context), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } + + return widget; + }, + ), + ); + } + + Future authenticate(BuildContext context) async { + AuthInfoApi authInfoApi = AuthInfoApi(); + var info = await authInfoApi.getAuthInfo(); + + LoginManager loginManager = LoginManager(info); + + var token = await loginManager.login(info, context); + } +} diff --git a/lib/player.dart b/lib/views/player.dart similarity index 96% rename from lib/player.dart rename to lib/views/player.dart index 3305087..8f85ad1 100644 --- a/lib/player.dart +++ b/lib/views/player.dart @@ -3,9 +3,10 @@ import 'package:flutter/services.dart'; import 'package:media_kit/media_kit.dart'; import 'package:media_kit_video/media_kit_video.dart'; import 'package:open_media_server_app/apis/base_api.dart'; -import 'package:open_media_server_app/player_controls/material_tv.dart'; +import 'package:open_media_server_app/globals/platform_globals.dart'; +import 'package:open_media_server_app/widgets/player_controls/material_tv.dart'; import 'package:open_media_server_app/helpers/wrapper.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/globals.dart'; class PlayerView extends StatefulWidget { const PlayerView({super.key, required this.url}); @@ -142,7 +143,7 @@ class _PlayerState extends State { : const SizedBox(), ]; - if (!Globals.isTv) { + if (!PlatformGlobals.isTv) { bottomButtonBar.add( const MaterialFullscreenButton(), ); @@ -230,7 +231,7 @@ class _PlayerState extends State { }, ); - if (Globals.isMobile) { + if (PlatformGlobals.isMobile) { return MaterialVideoControlsTheme( normal: mobileThemeData, fullscreen: mobileThemeData, @@ -243,7 +244,7 @@ class _PlayerState extends State { ), ), ); - } else if (Globals.isTv) { + } else if (PlatformGlobals.isTv) { return MaterialTvVideoControlsTheme( normal: tvThemeData, fullscreen: tvThemeData, diff --git a/lib/gallery_item.dart b/lib/widgets/gallery_item.dart similarity index 94% rename from lib/gallery_item.dart rename to lib/widgets/gallery_item.dart index 6af307e..e8ba099 100644 --- a/lib/gallery_item.dart +++ b/lib/widgets/gallery_item.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:open_media_server_app/globals.dart'; +import 'package:open_media_server_app/globals/globals.dart'; import 'package:open_media_server_app/models/internal/grid_item_model.dart'; import 'package:open_media_server_app/widgets/custom_image.dart'; diff --git a/lib/player_controls/material_tv.dart b/lib/widgets/player_controls/material_tv.dart similarity index 100% rename from lib/player_controls/material_tv.dart rename to lib/widgets/player_controls/material_tv.dart