diff --git a/filcnaplo/ios/Podfile.lock b/filcnaplo/ios/Podfile.lock index b50aa09..dbad45e 100644 --- a/filcnaplo/ios/Podfile.lock +++ b/filcnaplo/ios/Podfile.lock @@ -46,6 +46,8 @@ PODS: - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) + - live_activities (0.0.1): + - Flutter - open_file (0.0.1): - Flutter - path_provider_ios (0.0.1): @@ -77,6 +79,7 @@ DEPENDENCIES: - flutter_custom_tabs (from `.symlinks/plugins/flutter_custom_tabs/ios`) - flutter_foreground_task (from `.symlinks/plugins/flutter_foreground_task/ios`) - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) + - live_activities (from `.symlinks/plugins/live_activities/ios`) - open_file (from `.symlinks/plugins/open_file/ios`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) @@ -109,6 +112,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_foreground_task/ios" flutter_local_notifications: :path: ".symlinks/plugins/flutter_local_notifications/ios" + live_activities: + :path: ".symlinks/plugins/live_activities/ios" open_file: :path: ".symlinks/plugins/open_file/ios" path_provider_ios: @@ -141,6 +146,7 @@ SPEC CHECKSUMS: flutter_foreground_task: 21ef182ab0a29a3005cc72cd70e5f45cb7f7f817 flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + live_activities: 9ff56a06a2d43ecd68f56deeed13b18a8304789c open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce diff --git a/filcnaplo/ios/Runner.xcodeproj/project.pbxproj b/filcnaplo/ios/Runner.xcodeproj/project.pbxproj index 289e1ae..f372c0d 100644 --- a/filcnaplo/ios/Runner.xcodeproj/project.pbxproj +++ b/filcnaplo/ios/Runner.xcodeproj/project.pbxproj @@ -8,6 +8,13 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3127F78D28EAEDE200C2EFB3 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3127F75528EAECC800C2EFB3 /* WidgetKit.framework */; }; + 3127F78E28EAEDE200C2EFB3 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3127F75728EAECC800C2EFB3 /* SwiftUI.framework */; }; + 3127F79828EAEDE300C2EFB3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3127F79728EAEDE300C2EFB3 /* Assets.xcassets */; }; + 3127F79E28EAEDE300C2EFB3 /* livecard.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 3127F78C28EAEDE200C2EFB3 /* livecard.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 3127F7A428EAEE3D00C2EFB3 /* livecard.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A328EAEE3D00C2EFB3 /* livecard.intentdefinition */; }; + 3127F7A628EAEE5900C2EFB3 /* livecard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A528EAEE5900C2EFB3 /* livecard.swift */; }; + 3127F7A828EAEE8500C2EFB3 /* lesson_model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */; }; 373A6ECB5FC71FE9D8AF2EDB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F0ADD56276103500A3016C8 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; @@ -16,7 +23,28 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 3127F79C28EAEDE300C2EFB3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3127F78B28EAEDE200C2EFB3; + remoteInfo = livecardExtension; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ + 3127F74F28EAEC8A00C2EFB3 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 3127F79E28EAEDE300C2EFB3 /* livecard.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -33,6 +61,16 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 1F0ADD56276103500A3016C8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3127F73928EAEC3200C2EFB3 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 3127F73F28EAEC8A00C2EFB3 /* IntentsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IntentsUI.framework; path = System/Library/Frameworks/IntentsUI.framework; sourceTree = SDKROOT; }; + 3127F75528EAECC800C2EFB3 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + 3127F75728EAECC800C2EFB3 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; + 3127F78C28EAEDE200C2EFB3 /* livecard.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = livecard.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 3127F79728EAEDE300C2EFB3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 3127F79928EAEDE300C2EFB3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3127F7A328EAEE3D00C2EFB3 /* livecard.intentdefinition */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.intentdefinition; path = livecard.intentdefinition; sourceTree = ""; }; + 3127F7A528EAEE5900C2EFB3 /* livecard.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = livecard.swift; sourceTree = ""; tabWidth = 2; }; + 3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = lesson_model.swift; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 707F8089D970F81C480F73C4 /* 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 = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; @@ -50,6 +88,15 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 3127F78928EAEDE200C2EFB3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3127F78E28EAEDE200C2EFB3 /* SwiftUI.framework in Frameworks */, + 3127F78D28EAEDE200C2EFB3 /* WidgetKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -61,10 +108,25 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3127F78F28EAEDE200C2EFB3 /* livecard */ = { + isa = PBXGroup; + children = ( + 3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */, + 3127F7A328EAEE3D00C2EFB3 /* livecard.intentdefinition */, + 3127F79728EAEDE300C2EFB3 /* Assets.xcassets */, + 3127F79928EAEDE300C2EFB3 /* Info.plist */, + 3127F7A528EAEE5900C2EFB3 /* livecard.swift */, + ); + path = livecard; + sourceTree = ""; + }; 6640A963014A9D4F31026053 /* Frameworks */ = { isa = PBXGroup; children = ( 1F0ADD56276103500A3016C8 /* Pods_Runner.framework */, + 3127F73F28EAEC8A00C2EFB3 /* IntentsUI.framework */, + 3127F75528EAECC800C2EFB3 /* WidgetKit.framework */, + 3127F75728EAECC800C2EFB3 /* SwiftUI.framework */, ); name = Frameworks; sourceTree = ""; @@ -95,6 +157,7 @@ children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, + 3127F78F28EAEDE200C2EFB3 /* livecard */, 97C146EF1CF9000F007C117D /* Products */, 91FEB6212755D596FFFFEC73 /* Pods */, 6640A963014A9D4F31026053 /* Frameworks */, @@ -105,6 +168,7 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, + 3127F78C28EAEDE200C2EFB3 /* livecard.appex */, ); name = Products; sourceTree = ""; @@ -112,6 +176,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 3127F73928EAEC3200C2EFB3 /* Runner.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -127,6 +192,23 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 3127F78B28EAEDE200C2EFB3 /* livecard */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3127F79F28EAEDE300C2EFB3 /* Build configuration list for PBXNativeTarget "livecard" */; + buildPhases = ( + 3127F78828EAEDE200C2EFB3 /* Sources */, + 3127F78928EAEDE200C2EFB3 /* Frameworks */, + 3127F78A28EAEDE200C2EFB3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = livecard; + productName = livecardExtension; + productReference = 3127F78C28EAEDE200C2EFB3 /* livecard.appex */; + productType = "com.apple.product-type.app-extension"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; @@ -139,10 +221,12 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 71459C0EB905E05018E3D78F /* [CP] Embed Pods Frameworks */, + 3127F74F28EAEC8A00C2EFB3 /* Embed Foundation Extensions */, ); buildRules = ( ); dependencies = ( + 3127F79D28EAEDE300C2EFB3 /* PBXTargetDependency */, ); name = Runner; productName = Runner; @@ -155,9 +239,13 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 1410; LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { + 3127F78B28EAEDE200C2EFB3 = { + CreatedOnToolsVersion = 14.1; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -178,11 +266,20 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, + 3127F78B28EAEDE200C2EFB3 /* livecard */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 3127F78A28EAEDE200C2EFB3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3127F79828EAEDE300C2EFB3 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -267,6 +364,16 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 3127F78828EAEDE200C2EFB3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3127F7A828EAEE8500C2EFB3 /* lesson_model.swift in Sources */, + 3127F7A428EAEE3D00C2EFB3 /* livecard.intentdefinition in Sources */, + 3127F7A628EAEE5900C2EFB3 /* livecard.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -278,6 +385,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 3127F79D28EAEDE300C2EFB3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3127F78B28EAEDE200C2EFB3 /* livecard */; + targetProxy = 3127F79C28EAEDE300C2EFB3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -353,9 +468,12 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = MYUTW2GF6J; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -370,6 +488,119 @@ }; name = Profile; }; + 3127F7A028EAEDE300C2EFB3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = MYUTW2GF6J; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = livecard/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = livecard; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSSupportsLiveActivities = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecard; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3127F7A128EAEDE300C2EFB3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = MYUTW2GF6J; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = livecard/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = livecard; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSSupportsLiveActivities = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecard; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 3127F7A228EAEDE300C2EFB3 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = MYUTW2GF6J; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = livecard/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = livecard; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSSupportsLiveActivities = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecard; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -483,9 +714,12 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = MYUTW2GF6J; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -505,9 +739,12 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = MYUTW2GF6J; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -525,6 +762,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 3127F79F28EAEDE300C2EFB3 /* Build configuration list for PBXNativeTarget "livecard" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3127F7A028EAEDE300C2EFB3 /* Debug */, + 3127F7A128EAEDE300C2EFB3 /* Release */, + 3127F7A228EAEDE300C2EFB3 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/filcnaplo/ios/Runner/Info.plist b/filcnaplo/ios/Runner/Info.plist index a59e4e6..7275bb5 100644 --- a/filcnaplo/ios/Runner/Info.plist +++ b/filcnaplo/ios/Runner/Info.plist @@ -22,6 +22,8 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + NSSupportsLiveActivities + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/filcnaplo/ios/Runner/Runner.entitlements b/filcnaplo/ios/Runner/Runner.entitlements index dec5aa2..903def2 100644 --- a/filcnaplo/ios/Runner/Runner.entitlements +++ b/filcnaplo/ios/Runner/Runner.entitlements @@ -1,8 +1,8 @@ - - aps-environment - production - - \ No newline at end of file + + aps-environment + development + + diff --git a/filcnaplo/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json b/filcnaplo/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/filcnaplo/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/filcnaplo/ios/livecard/Assets.xcassets/AppIcon.appiconset/Contents.json b/filcnaplo/ios/livecard/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/filcnaplo/ios/livecard/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/filcnaplo/ios/livecard/Assets.xcassets/Contents.json b/filcnaplo/ios/livecard/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/filcnaplo/ios/livecard/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/filcnaplo/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json b/filcnaplo/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/filcnaplo/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/filcnaplo/ios/livecard/Info.plist b/filcnaplo/ios/livecard/Info.plist new file mode 100644 index 0000000..0f118fb --- /dev/null +++ b/filcnaplo/ios/livecard/Info.plist @@ -0,0 +1,11 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.widgetkit-extension + + + diff --git a/filcnaplo/ios/livecard/lesson_model.swift b/filcnaplo/ios/livecard/lesson_model.swift new file mode 100644 index 0000000..81671f1 --- /dev/null +++ b/filcnaplo/ios/livecard/lesson_model.swift @@ -0,0 +1,27 @@ +import Foundation + +class LessonData { + var icon: String + var index: String + var title: String + var subtitle: String + var description: String + var startDate: Date + var endDate: Date + var date: ClosedRange + var nextSubject: String + var nextRoom: String + + init?(JSONData data:[String: String]) { + self.icon = data["icon"]! + self.index = data["index"]! + self.title = data["title"]! + self.subtitle = data["subtitle"]! + self.description = data["description"]! + self.startDate = Date(timeIntervalSince1970: Double(data["startDate"]!)! / 1000) + self.endDate = Date(timeIntervalSince1970: Double(data["endDate"]!)! / 1000) + date = self.startDate...self.endDate + self.nextSubject = data["nextSubject"]! + self.nextRoom = data["nextRoom"]! + } +} diff --git a/filcnaplo/ios/livecard/livecard.intentdefinition b/filcnaplo/ios/livecard/livecard.intentdefinition new file mode 100644 index 0000000..bdb4045 --- /dev/null +++ b/filcnaplo/ios/livecard/livecard.intentdefinition @@ -0,0 +1,59 @@ + + + + + INEnums + + INIntentDefinitionModelVersion + 1.2 + INIntentDefinitionNamespace + 88xZPY + INIntentDefinitionSystemVersion + 20A294 + INIntentDefinitionToolsBuildVersion + 12A6144 + INIntentDefinitionToolsVersion + 12.0 + INIntents + + + INIntentCategory + information + INIntentDescriptionID + tVvJ9c + INIntentEligibleForWidgets + + INIntentIneligibleForSuggestions + + INIntentName + Configuration + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Configuration + INIntentTitleID + gpCwrM + INIntentType + Custom + INIntentVerb + View + + + INTypes + + + diff --git a/filcnaplo/ios/livecard/livecard.swift b/filcnaplo/ios/livecard/livecard.swift new file mode 100644 index 0000000..51ef346 --- /dev/null +++ b/filcnaplo/ios/livecard/livecard.swift @@ -0,0 +1,137 @@ +import ActivityKit +import WidgetKit +import SwiftUI + +@main +struct Widgets: WidgetBundle { + var body: some Widget { + if #available(iOS 16.1, *) { + LiveCardWidget() + } + } +} + +// We need to redefined live activities pipe +struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable { + public typealias LiveDeliveryData = ContentState + + public struct ContentState: Codable, Hashable { + var data: Dictionary + } + + var id = UUID() +} + +@available(iOSApplicationExtension 16.1, *) +struct LiveCardWidget: Widget { + var body: some WidgetConfiguration { + /// Live Activity Notification + ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in + let lesson = LessonData(JSONData: context.state.data) + + HStack(alignment: .center) { + Image(systemName: lesson!.icon) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: CGFloat(30), height: CGFloat(30)) + .padding(.leading, CGFloat(8)) + + VStack(alignment: .leading) { + Text(lesson!.index + lesson!.title) + .font(.title3) + .bold() + + Text(lesson!.description) + .font(.subheadline) + + Spacer() + + HStack { + Image(systemName: "arrow.right") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: CGFloat(12), height: CGFloat(12)) + Text(lesson!.nextSubject) + .font(.caption) + Text(lesson!.nextRoom) + .font(.caption2) + } + }.padding(15) + + Spacer() + + Text(lesson!.subtitle) + .font(.subheadline) + .padding(.trailing, 12) + }.padding(12) + /// Dynamic Island + } dynamicIsland: { context in + let lesson = LessonData(JSONData: context.state.data) + + /// Expanded + return DynamicIsland { + DynamicIslandExpandedRegion(.leading) { + VStack { + Spacer() + Image(systemName: lesson!.icon) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: CGFloat(30), height: CGFloat(30)) + .padding(.leading, CGFloat(6)) + .padding(.bottom, CGFloat(6)) + } + } + DynamicIslandExpandedRegion(.center) { + VStack(alignment: .leading) { + Text(lesson!.index + lesson!.title) + .lineLimit(1) + .font(.title3) + .bold() + + Text(lesson!.description) + .lineLimit(2) + .font(.caption) + } + } + DynamicIslandExpandedRegion(.trailing) { + VStack { + Spacer() + Text(lesson!.subtitle) + .lineLimit(1) + .font(.subheadline) + Spacer() + } + } + + /// Compact + } compactLeading: { + Label { + Text(lesson!.title) + } icon: { + Image(systemName: lesson!.icon) + } + .font(.caption2) + } compactTrailing: { + Text(timerInterval: lesson!.date, countsDown: true) + .multilineTextAlignment(.center) + .frame(width: 40) + .font(.caption2) + + /// Collapsed + } minimal: { + VStack(alignment: .center) { + Image(systemName: lesson!.icon) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: CGFloat(12), height: CGFloat(12)) + + Text(timerInterval: lesson!.date, countsDown: true) + .multilineTextAlignment(.center) + .monospacedDigit() + .font(.system(size: CGFloat(10))) + } + } + .keylineTint(.accentColor) + } + } +} diff --git a/filcnaplo/lib/api/login.dart b/filcnaplo/lib/api/login.dart index 3e14777..ee55339 100644 --- a/filcnaplo/lib/api/login.dart +++ b/filcnaplo/lib/api/login.dart @@ -23,7 +23,7 @@ import 'package:filcnaplo/api/nonce.dart'; enum LoginState { missingFields, invalidGrant, failed, normal, inProgress, success } -Nonce getNonce(BuildContext context, String nonce, String username, String instituteCode) { +Nonce getNonce(String nonce, String username, String instituteCode) { Nonce nonceEncoder = Nonce(key: [98, 97, 83, 115, 120, 79, 119, 108, 85, 49, 106, 77], nonce: nonce); nonceEncoder.encode(instituteCode.toUpperCase() + nonce + username.toUpperCase()); @@ -46,7 +46,7 @@ Future loginApi({ String nonceStr = await Provider.of(context, listen: false).getAPI(KretaAPI.nonce, json: false); - Nonce nonce = getNonce(context, nonceStr, username, instituteCode); + Nonce nonce = getNonce(nonceStr, username, instituteCode); headers.addAll(nonce.header()); Map? res = await Provider.of(context, listen: false).postAPI(KretaAPI.login, diff --git a/filcnaplo/lib/api/providers/live_card_provider.dart b/filcnaplo/lib/api/providers/live_card_provider.dart new file mode 100644 index 0000000..5312afc --- /dev/null +++ b/filcnaplo/lib/api/providers/live_card_provider.dart @@ -0,0 +1,198 @@ +// ignore_for_file: no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:io'; + +import 'package:filcnaplo/helpers/subject.dart'; +import 'package:filcnaplo/models/settings.dart'; +import 'package:filcnaplo_kreta_api/models/lesson.dart'; +import 'package:filcnaplo_kreta_api/models/week.dart'; +import 'package:filcnaplo/utils/format.dart'; +import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart'; +import 'package:flutter/widgets.dart'; +import 'package:live_activities/live_activities.dart'; + +enum LiveCardState { empty, duringLesson, duringBreak, morning, afternoon, night } + +class LiveCardProvider extends ChangeNotifier { + Lesson? currentLesson; + Lesson? nextLesson; + Lesson? prevLesson; + List? nextLessons; + + LiveCardState currentState = LiveCardState.empty; + late Timer _timer; + late final TimetableProvider _lessonProvider; + late final SettingsProvider _settingsProvider; + + late Duration _delay; + + final _liveActivitiesPlugin = LiveActivities(); + String? _latestActivityId; + Map _lastActivity = {}; + + LiveCardProvider({ + required TimetableProvider lessonProvider, + required SettingsProvider settingsProvider, + }) : _lessonProvider = lessonProvider, + _settingsProvider = settingsProvider { + _timer = Timer.periodic(const Duration(seconds: 1), (timer) => update()); + lessonProvider.restore().then((_) => update()); + _delay = settingsProvider.bellDelayEnabled ? Duration(seconds: settingsProvider.bellDelay) : Duration.zero; + } + + @override + void dispose() { + _timer.cancel(); + if (_latestActivityId != null && Platform.isIOS) _liveActivitiesPlugin.endActivity(_latestActivityId!); + super.dispose(); + } + + // Debugging + static DateTime _now() { + return DateTime.now(); + } + + String getFloorDifference() { + final prevFloor = prevLesson!.getFloor(); + final nextFloor = nextLesson!.getFloor(); + if (prevFloor == null || nextFloor == null || prevFloor == nextFloor) { + return "to room"; + } + if (nextFloor == 0) { + return "ground floor"; + } + if (nextFloor > prevFloor) { + return "up floor"; + } else { + return "down floor"; + } + } + + Map toMap() { + switch (currentState) { + case LiveCardState.duringLesson: + return { + "icon": currentLesson != null ? SubjectIcon.resolve(subject: currentLesson?.subject).name : "book", + "index": currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "", + "title": currentLesson != null ? ShortSubject.resolve(subject: currentLesson?.subject).capital() : "", + "subtitle": currentLesson?.room.replaceAll("_", " ") ?? "", + "description": currentLesson?.description ?? "", + "startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(), + "endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(), + "nextSubject": nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject).capital() : "", + "nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "", + }; + case LiveCardState.duringBreak: + final iconFloorMap = { + "to room": "chevron.right.2", + "up floor": "arrow.up.right", + "down floor": "arrow.down.left", + "ground floor": "arrow.down.left", + }; + + final diff = getFloorDifference(); + + return { + "icon": iconFloorMap[diff] ?? "cup.and.saucer", + "title": "Szünet", + "description": "Maradj ebben a teremben.", + "startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(), + "endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(), + "nextSubject": nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject) : "", + "nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "", + "index": "", + "subtitle": "", + }; + default: + return {}; + } + } + + void update() async { + if (Platform.isIOS) { + final cmap = toMap(); + if (cmap != _lastActivity) { + _lastActivity = cmap; + + if (_lastActivity != {}) { + if (_latestActivityId == null) { + _liveActivitiesPlugin.createActivity(_lastActivity).then((value) => _latestActivityId = value); + } else { + _liveActivitiesPlugin.updateActivity(_latestActivityId!, _lastActivity); + } + } else { + if (_latestActivityId != null) _liveActivitiesPlugin.endActivity(_latestActivityId!); + } + } + } + + List today = _today(_lessonProvider); + + if (today.isEmpty) { + await _lessonProvider.fetch(week: Week.current()); + today = _today(_lessonProvider); + } + + _delay = _settingsProvider.bellDelayEnabled ? Duration(seconds: _settingsProvider.bellDelay) : Duration.zero; + + final now = _now().add(_delay); + + // Filter cancelled lessons #20 + today = today.where((lesson) => lesson.status?.name != "Elmaradt").toList(); + + if (today.isNotEmpty) { + // sort + today.sort((a, b) => a.start.compareTo(b.start)); + + final _lesson = today.firstWhere((l) => l.start.isBefore(now) && l.end.isAfter(now), orElse: () => Lesson.fromJson({})); + + if (_lesson.start.year != 0) { + currentLesson = _lesson; + } else { + currentLesson = null; + } + + final _next = today.firstWhere((l) => l.start.isAfter(_now()), orElse: () => Lesson.fromJson({})); + nextLessons = today.where((l) => l.start.isAfter(_now())).toList(); + + if (_next.start.year != 0) { + nextLesson = _next; + } else { + nextLesson = null; + } + + final _prev = today.lastWhere((l) => l.end.isBefore(now), orElse: () => Lesson.fromJson({})); + + if (_prev.start.year != 0) { + prevLesson = _prev; + } else { + prevLesson = null; + } + } + + if (currentLesson != null) { + currentState = LiveCardState.duringLesson; + } else if (nextLesson != null && prevLesson != null) { + currentState = LiveCardState.duringBreak; + } else if (now.hour >= 12 && now.hour < 20) { + currentState = LiveCardState.afternoon; + } else if (now.hour >= 20) { + currentState = LiveCardState.night; + } else if (now.hour >= 5 && now.hour <= 10) { + currentState = LiveCardState.morning; + } else { + currentState = LiveCardState.empty; + } + + notifyListeners(); + } + + bool get show => currentState != LiveCardState.empty; + + Duration get delay => _delay; + + bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day); + + List _today(TimetableProvider p) => p.lessons.where((l) => _sameDate(l.date, _now())).toList(); +} diff --git a/filcnaplo/lib/app.dart b/filcnaplo/lib/app.dart index f4bd1d4..6b27a4d 100644 --- a/filcnaplo/lib/app.dart +++ b/filcnaplo/lib/app.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:filcnaplo/api/client.dart'; +import 'package:filcnaplo/api/providers/live_card_provider.dart'; import 'package:filcnaplo/api/providers/news_provider.dart'; import 'package:filcnaplo/api/providers/database_provider.dart'; import 'package:filcnaplo/api/providers/status_provider.dart'; @@ -69,30 +70,35 @@ class App extends StatelessWidget { CorePalette? corePalette; + final status = StatusProvider(); + final kreta = KretaClient(user: user, settings: settings, status: status); + final timetable = TimetableProvider(user: user, database: database, kreta: kreta); + return I18n( initialLocale: Locale(settings.language, settings.language.toUpperCase()), child: MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => settings), ChangeNotifierProvider(create: (_) => user), - ChangeNotifierProvider(create: (context) => StatusProvider()), - Provider(create: (context) => KretaClient(context: context, userAgent: settings.config.userAgent)), + ChangeNotifierProvider(create: (_) => status), + Provider(create: (_) => kreta), Provider(create: (context) => database), ChangeNotifierProvider(create: (context) => ThemeModeObserver(initialTheme: settings.theme)), ChangeNotifierProvider(create: (context) => NewsProvider(context: context)), ChangeNotifierProvider(create: (context) => UpdateProvider(context: context)), - + // User data providers ChangeNotifierProvider(create: (context) => GradeProvider(context: context)), - ChangeNotifierProvider(create: (context) => TimetableProvider(context: context)), + ChangeNotifierProvider(create: (_) => timetable), ChangeNotifierProvider(create: (context) => ExamProvider(context: context)), ChangeNotifierProvider(create: (context) => HomeworkProvider(context: context)), ChangeNotifierProvider(create: (context) => MessageProvider(context: context)), ChangeNotifierProvider(create: (context) => NoteProvider(context: context)), ChangeNotifierProvider(create: (context) => EventProvider(context: context)), ChangeNotifierProvider(create: (context) => AbsenceProvider(context: context)), - + ChangeNotifierProvider(create: (context) => GradeCalculatorProvider(context)), + ChangeNotifierProvider(create: (context) => LiveCardProvider(lessonProvider: timetable, settingsProvider: settings)) ], child: Consumer( builder: (context, themeMode, child) { @@ -104,7 +110,7 @@ class App extends StatelessWidget { builder: (context, child) { // Limit font size scaling to 1.0 double textScaleFactor = min(MediaQuery.of(context).textScaleFactor, 1.0); - + return MediaQuery( data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor), child: child ?? Container(), @@ -127,14 +133,14 @@ class App extends StatelessWidget { ], localeListResolutionCallback: (locales, supported) { Locale locale = const Locale('hu', 'HU'); - + for (var loc in locales ?? []) { if (supported.contains(loc)) { locale = loc; break; } } - + return locale; }, onGenerateRoute: (settings) => rootNavigator(settings), diff --git a/filcnaplo/lib/helpers/subject.dart b/filcnaplo/lib/helpers/subject.dart new file mode 100644 index 0000000..06aa842 --- /dev/null +++ b/filcnaplo/lib/helpers/subject.dart @@ -0,0 +1,119 @@ +import 'package:filcnaplo/icons/filc_icons.dart'; +import 'package:filcnaplo/utils/format.dart'; +import 'package:filcnaplo_kreta_api/models/subject.dart'; +import 'package:flutter/cupertino.dart'; + +class SubjectIconData { + final IconData data; + final String name; // for iOS live activities compatibilty + + SubjectIconData({ + this.data = CupertinoIcons.rectangle_grid_2x2, + this.name = "square.grid.2x2", + }); +} + +class SubjectIcon { + static SubjectIconData resolve({Subject? subject, String? subjectName}) { + assert(!(subject == null && subjectName == null)); + + String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim(); + String category = subject?.category.description.toLowerCase().specialChars() ?? ""; + + // todo: check for categories + if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") { + return SubjectIconData(data: CupertinoIcons.function, name: "function"); + } else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.textformat_alt, name: "textformat.alt"); + } else if (RegExp("irodalom").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.book, name: "book"); + } else if (RegExp("tor(i|tenelem)").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.compass, name: "safari"); + } else if (RegExp("foldrajz").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.map, name: "map"); + } else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.paintbrush, name: "paintbrush"); + } else if (RegExp("fizika").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.lightbulb, name: "lightbulb"); + } else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.music_note, name: "music.note"); + } else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.sportscourt, name: "sportscourt"); + } else if (RegExp("kemia").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.lab_flask, name: "testtube.2"); + } else if (RegExp("biologia").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.paw, name: "pawprint"); + } else if (RegExp("kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.arrow_3_trianglepath, name: "arrow.3.trianglepath"); + } else if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.heart, name: "heart"); + } else if (RegExp("penzugy").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.money_dollar, name: "dollarsign"); + } else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.device_laptop, name: "laptopcomputer"); + } else if (RegExp("prog").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.chevron_left_slash_chevron_right, name: "chevron.left.forwardslash.chevron.right"); + } else if (RegExp("halozat").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.antenna_radiowaves_left_right, name: "antenna.radiowaves.left.and.right"); + } else if (RegExp("szinhaz").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.hifispeaker, name: "hifispeaker"); + } else if (RegExp("film|media").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.film, name: "film"); + } else if (RegExp("elektro(tech)?nika").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.bolt, name: "bolt"); + } else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.wrench, name: "wrench"); + } else if (RegExp("technika").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.hammer, name: "hammer"); + } else if (RegExp("tanc").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.music_mic, name: "music.mic"); + } else if (RegExp("filozofia").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.bubble_left, name: "bubble.left"); + } else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) || name == "ofo") { + return SubjectIconData(data: CupertinoIcons.group, name: "person.3"); + } else if (RegExp("gazdasag").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.chart_pie, name: "chart.pie"); + } else if (RegExp("szorgalom").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.checkmark_seal, name: "checkmark.seal"); + } else if (RegExp("magatartas").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.smiley, name: "face.smiling"); + } else if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) { + return SubjectIconData(data: CupertinoIcons.globe, name: "globe"); + } else if (RegExp("linux").hasMatch(name)) { + return SubjectIconData(data: FilcIcons.linux); + } + + return SubjectIconData(); + } +} + +class ShortSubject { + static String resolve({Subject? subject, String? subjectName}) { + assert(!(subject == null && subjectName == null)); + + String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim(); + // String category = subject?.category.description.toLowerCase().specialChars() ?? ""; + + if (RegExp("magyar irodalom").hasMatch(name)) { + return "Irodalom"; + } else if (RegExp("magyar nyelv").hasMatch(name)) { + return "Nyelvtan"; + } else if (RegExp("matematika").hasMatch(name)) { + return "Matek"; + } else if (RegExp("digitalis kultura").hasMatch(name)) { + return "Dig. kult."; + } else if (RegExp("testneveles").hasMatch(name)) { + return "Tesi"; + } else if (RegExp("tortenelem").hasMatch(name)) { + return "Töri"; + } else if (RegExp("(angol|nemet|francia|olasz|orosz|spanyol|latin|kinai) nyelv").hasMatch(name)) { + return (subject?.name ?? subjectName ?? "?").replaceAll(" nyelv", ""); + } else if (RegExp("informatika").hasMatch(name)) { + return "Infó"; + } else if (RegExp("osztalyfonoki").hasMatch(name)) { + return "Ofő"; + } + + return subject?.name.capital() ?? subjectName?.capital() ?? "?"; + } +} diff --git a/filcnaplo/lib/helpers/subject_icon.dart b/filcnaplo/lib/helpers/subject_icon.dart deleted file mode 100644 index 4f81cbb..0000000 --- a/filcnaplo/lib/helpers/subject_icon.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:filcnaplo/icons/filc_icons.dart'; -import 'package:filcnaplo/utils/format.dart'; -import 'package:filcnaplo_kreta_api/models/subject.dart'; -import 'package:flutter/material.dart'; - -class SubjectIcon { - static IconData? lookup({Subject? subject, String? subjectName}) { - assert(!(subject == null && subjectName == null)); - - String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim(); - String category = subject?.category.description.toLowerCase().specialChars() ?? ""; - - // todo: check for categories - if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") return Icons.calculate_outlined; - if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) return Icons.spellcheck_outlined; - if (RegExp("irodalom").hasMatch(name)) return Icons.menu_book_outlined; - if (RegExp("tor(i|tenelem)").hasMatch(name)) return Icons.hourglass_empty_outlined; - if (RegExp("foldrajz").hasMatch(name)) return Icons.public_outlined; - if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) return Icons.palette_outlined; - if (RegExp("fizika").hasMatch(name)) return Icons.emoji_objects_outlined; - if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) return Icons.music_note_outlined; - if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) return Icons.sports_soccer_outlined; - if (RegExp("kemia").hasMatch(name)) return Icons.science_outlined; - if (RegExp("biologia").hasMatch(name)) return Icons.pets_outlined; - if (RegExp("kornyezet|termeszet(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) return Icons.eco_outlined; - if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) return Icons.favorite_border_outlined; - if (RegExp("penzugy").hasMatch(name)) return Icons.savings_outlined; - if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) return Icons.computer_outlined; - if (RegExp("prog").hasMatch(name)) return Icons.code_outlined; - if (RegExp("halozat").hasMatch(name)) return Icons.wifi_tethering_outlined; - if (RegExp("szinhaz").hasMatch(name)) return Icons.theater_comedy_outlined; - if (RegExp("film|media").hasMatch(name)) return Icons.theaters_outlined; - if (RegExp("elektro(tech)?nika").hasMatch(name)) return Icons.electrical_services_outlined; - if (RegExp("gepesz|mernok|ipar").hasMatch(name)) return Icons.precision_manufacturing_outlined; - if (RegExp("technika").hasMatch(name)) return Icons.build_outlined; - if (RegExp("tanc").hasMatch(name)) return Icons.speaker_outlined; - if (RegExp("filozofia").hasMatch(name)) return Icons.psychology_outlined; - if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) || name == "ofo") return Icons.groups_outlined; - if (RegExp("gazdasag").hasMatch(name)) return Icons.account_balance_outlined; - if (RegExp("szorgalom").hasMatch(name)) return Icons.verified_outlined; - if (RegExp("magatartas").hasMatch(name)) return Icons.emoji_people_outlined; - if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) return Icons.translate_outlined; - if (RegExp("linux").hasMatch(name)) return FilcIcons.linux; - return Icons.widgets_outlined; - } -} diff --git a/filcnaplo/lib/ui/widgets/grade/grade_tile.dart b/filcnaplo/lib/ui/widgets/grade/grade_tile.dart index 0c3af26..ffa40be 100644 --- a/filcnaplo/lib/ui/widgets/grade/grade_tile.dart +++ b/filcnaplo/lib/ui/widgets/grade/grade_tile.dart @@ -1,7 +1,7 @@ import 'package:filcnaplo/models/settings.dart'; import 'package:filcnaplo/theme/colors/colors.dart'; import 'package:filcnaplo_kreta_api/models/grade.dart'; -import 'package:filcnaplo/helpers/subject_icon.dart'; +import 'package:filcnaplo/helpers/subject.dart'; import 'package:filcnaplo/utils/format.dart'; import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart'; import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart'; @@ -79,7 +79,11 @@ class GradeTile extends StatelessWidget { child: Center( child: Padding( padding: leadingPadding, - child: Icon(SubjectIcon.lookup(subject: grade.subject), size: 28.0, color: AppColors.of(context).text.withOpacity(.75)), + child: Icon( + SubjectIcon.resolve(subject: grade.subject).data, + size: 28.0, + color: AppColors.of(context).text.withOpacity(.75), + ), ), ), ), diff --git a/filcnaplo/pubspec.yaml b/filcnaplo/pubspec.yaml index 539fd37..e9f7fd4 100644 --- a/filcnaplo/pubspec.yaml +++ b/filcnaplo/pubspec.yaml @@ -48,10 +48,9 @@ dependencies: flutter_feather_icons: ^2.0.0+1 flutter_foreground_task: ^3.9.0 flutter_local_notifications: ^11.0.0 + live_activities: ^1.0.0 dev_dependencies: - flutter_test: - sdk: flutter flutter_lints: ^2.0.1 # flutter_launcher_icons: ^0.9.0 # flutter_native_splash: ^1.2.0 diff --git a/filcnaplo_mobile_ui b/filcnaplo_mobile_ui index f6cc4a0..9a396a0 160000 --- a/filcnaplo_mobile_ui +++ b/filcnaplo_mobile_ui @@ -1 +1 @@ -Subproject commit f6cc4a0ace62f3c5b3de8e86bfc7005d33faa2b5 +Subproject commit 9a396a08423f4a2e2008dcedeff90db18999cfcf