├── Media ├── Icon.png ├── bmc_qr.png ├── AppIcons │ ├── logo_128.png │ ├── logo_16.png │ ├── logo_256.png │ ├── logo_32.png │ ├── logo_512.png │ ├── logo_64.png │ └── logo_1024.png ├── Screenshots │ ├── v2 │ │ ├── tags_v2.png │ │ ├── start_v2.png │ │ └── settings_v2.png │ └── v4 │ │ ├── output_v4.png │ │ ├── script_v4.png │ │ ├── start_v4.png │ │ └── settings_v4.png └── StatusBarIcon.svg ├── ScriptManager ├── Assets.xcassets │ ├── Contents.json │ ├── bmc_qr.imageset │ │ ├── bmc_qr.png │ │ └── Contents.json │ ├── Logo.imageset │ │ ├── Vectorlogo.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── logo_1024.png │ │ ├── logo_128.png │ │ ├── logo_256.png │ │ ├── logo_32 1.png │ │ ├── logo_32.png │ │ ├── logo_512.png │ │ ├── logo_64.png │ │ ├── logo_16 (1).png │ │ ├── logo_256 1.png │ │ ├── logo_512 1.png │ │ └── Contents.json │ └── StatusBarIcon.imageset │ │ ├── Contents.json │ │ └── StatusBarIcon.svg ├── Colors.xcassets │ ├── Contents.json │ ├── Signals │ │ ├── Contents.json │ │ ├── Danger.colorset │ │ │ └── Contents.json │ │ ├── Success.colorset │ │ │ └── Contents.json │ │ └── Warning.colorset │ │ │ └── Contents.json │ ├── Tag-Presets │ │ ├── Contents.json │ │ ├── Archive.colorset │ │ │ └── Contents.json │ │ ├── Favs.colorset │ │ │ └── Contents.json │ │ ├── Files.colorset │ │ │ └── Contents.json │ │ ├── Fixes.colorset │ │ │ └── Contents.json │ │ └── GitLab.colorset │ │ │ └── Contents.json │ ├── Secondary.colorset │ │ └── Contents.json │ ├── Primary.colorset │ │ └── Contents.json │ └── Creme.colorset │ │ └── Contents.json ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── ScriptManager.entitlements ├── Models │ ├── ScriptProcessModel.swift │ ├── TagPresetModel.swift │ ├── DataModel.swift │ ├── ScriptPresetModel.swift │ ├── UserdataModel.swift │ ├── ShortcutModel.swift │ ├── ResultModel.swift │ ├── CronJobModel.swift │ ├── ScriptTimeModel.swift │ ├── TagModel.swift │ ├── ShellModel.swift │ ├── SettingsModel.swift │ └── ScriptModel.swift ├── ViewModels │ ├── InfoViewModel.swift │ ├── BackupViewModel.swift │ ├── AlertViewModel.swift │ ├── HintViewModel.swift │ ├── MainViewModel.swift │ ├── ModalViewModel.swift │ ├── HeaderViewModel.swift │ ├── TagViewModel.swift │ └── SettingsViewModel.swift ├── Info.plist ├── Utils │ ├── IconSize.swift │ ├── Spacing.swift │ ├── AppColor.swift │ └── ScriptIcons.swift ├── Protocols │ ├── SettingsHandlerProtocol.swift │ ├── NotificationHandlerProtocol.swift │ ├── HintHandlerProtocol.swift │ ├── CronJobHandlerProtocol.swift │ ├── TagHandlerProtocol.swift │ ├── ModalHandlerProtocol.swift │ ├── StorageHandlerProtocol.swift │ ├── AlertHandlerProtocol.swift │ └── ScriptHandlerProtocol.swift ├── Extensions │ ├── ShortcutsExtension.swift │ ├── DateExtension.swift │ ├── IntervalExtension.swift │ └── ColorExtension.swift ├── Handler │ ├── SettingsHandler.swift │ ├── ModalHandler.swift │ ├── TagHandler.swift │ ├── HintHandler.swift │ ├── AlertHandler.swift │ ├── CronJobHandler.swift │ └── ScriptHandler.swift ├── Presets │ ├── TagPreset.swift │ └── ScriptPresets.swift ├── Views │ ├── Shortcuts │ │ └── ShortcutView.swift │ ├── Settings │ │ ├── SettingsAutostartView.swift │ │ ├── SettingsUnicodeView.swift │ │ ├── SettingsNotificationsView.swift │ │ ├── SettingsLoggingView.swift │ │ ├── SettingsBackupView.swift │ │ ├── SettingsShellView.swift │ │ └── SettingsShortcutView.swift │ ├── Scripts │ │ ├── AddScript │ │ │ ├── TagPickerView.swift │ │ │ └── IconPickerView.swift │ │ ├── ScriptRow │ │ │ ├── ScriptRowActions │ │ │ │ ├── ScriptDeleteButtonView.swift │ │ │ │ ├── ScriptDetailButtonView.swift │ │ │ │ ├── ScriptStateButtonView.swift │ │ │ │ └── ScriptRunButtonView.swift │ │ │ ├── ScriptRowView.swift │ │ │ ├── ScriptRowLabelView.swift │ │ │ └── ScriptDetailsView.swift │ │ ├── SearchbarView.swift │ │ ├── OutputWindowView.swift │ │ └── ScriptsListView.swift │ ├── Common │ │ ├── CustomButtonView.swift │ │ ├── HelpView.swift │ │ ├── BadgeView.swift │ │ ├── HintView.swift │ │ ├── AlertView.swift │ │ └── GroupView.swift │ ├── MainView.swift │ ├── Modals │ │ ├── InfoModal.swift │ │ ├── ModalView.swift │ │ ├── TagModalView.swift │ │ ├── AddModalView.swift │ │ └── SettingsModalView.swift │ ├── Tags │ │ └── TagsListView.swift │ └── HeaderView.swift ├── Storage │ ├── StorageHandlerMock.swift │ ├── StorageWrapper.swift │ └── StorageHandler.swift ├── Provider │ ├── JSONProvider.swift │ ├── NotificationProvider.swift │ └── BackupProvider.swift ├── DependencyRegistry.swift └── ScriptManagerApp.swift ├── ScriptManager.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved ├── xcuserdata │ └── Daniel.Filler.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── xcshareddata │ └── xcschemes │ ├── Tests.xcscheme │ └── ScriptManager.xcscheme ├── Tests ├── Handler │ ├── TagHandlerTests.swift │ ├── SettingsHandlerTests.swift │ ├── ModalHandlerTests.swift │ ├── HintHandlerTests.swift │ ├── AlertHandlerTests.swift │ ├── CronJobHandlerTests.swift │ └── ScriptHandlerTests.swift └── Extensions │ └── IntervalTests.swift ├── LICENSE.md └── README.md /Media/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/Icon.png -------------------------------------------------------------------------------- /Media/bmc_qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/bmc_qr.png -------------------------------------------------------------------------------- /Media/AppIcons/logo_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/AppIcons/logo_128.png -------------------------------------------------------------------------------- /Media/AppIcons/logo_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/AppIcons/logo_16.png -------------------------------------------------------------------------------- /Media/AppIcons/logo_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/AppIcons/logo_256.png -------------------------------------------------------------------------------- /Media/AppIcons/logo_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/AppIcons/logo_32.png -------------------------------------------------------------------------------- /Media/AppIcons/logo_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/AppIcons/logo_512.png -------------------------------------------------------------------------------- /Media/AppIcons/logo_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/AppIcons/logo_64.png -------------------------------------------------------------------------------- /Media/AppIcons/logo_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/AppIcons/logo_1024.png -------------------------------------------------------------------------------- /Media/Screenshots/v2/tags_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/Screenshots/v2/tags_v2.png -------------------------------------------------------------------------------- /Media/Screenshots/v2/start_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/Screenshots/v2/start_v2.png -------------------------------------------------------------------------------- /Media/Screenshots/v4/output_v4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/Screenshots/v4/output_v4.png -------------------------------------------------------------------------------- /Media/Screenshots/v4/script_v4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/Screenshots/v4/script_v4.png -------------------------------------------------------------------------------- /Media/Screenshots/v4/start_v4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/Screenshots/v4/start_v4.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Media/Screenshots/v2/settings_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/Screenshots/v2/settings_v2.png -------------------------------------------------------------------------------- /Media/Screenshots/v4/settings_v4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/Media/Screenshots/v4/settings_v4.png -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Signals/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Tag-Presets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScriptManager/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/bmc_qr.imageset/bmc_qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/bmc_qr.imageset/bmc_qr.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/Logo.imageset/Vectorlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/Logo.imageset/Vectorlogo.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_1024.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_128.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_256.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_32 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_32 1.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_32.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_512.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_64.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_16 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_16 (1).png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_256 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_256 1.png -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_512 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielFiller30/ScriptManager/HEAD/ScriptManager/Assets.xcassets/AppIcon.appiconset/logo_512 1.png -------------------------------------------------------------------------------- /ScriptManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScriptManager/ScriptManager.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ScriptManager.xcodeproj/xcuserdata/Daniel.Filler.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/Logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Vectorlogo.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/bmc_qr.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "bmc_qr.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ScriptManager/Models/ScriptProcessModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProcessModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | import Foundation 9 | 10 | struct ScriptProcess { 11 | var scriptId: UUID 12 | var process: Process 13 | } 14 | -------------------------------------------------------------------------------- /ScriptManager/ViewModels/InfoViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InfoViewModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | import Resolver 9 | 10 | class InfoViewModel { 11 | @LazyInjected var modalHandler: ModalHandlerProtocol 12 | } 13 | -------------------------------------------------------------------------------- /ScriptManager/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Application is agend (UIElement) 6 | YES 7 | 8 | 9 | -------------------------------------------------------------------------------- /ScriptManager/Models/TagPresetModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagPresetModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TagPreset: Hashable { 11 | var title: String 12 | var color: Color 13 | var icon: String 14 | } 15 | -------------------------------------------------------------------------------- /ScriptManager/Models/DataModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 16.07.24. 6 | // 7 | 8 | import KeyboardShortcuts 9 | import Foundation 10 | 11 | struct DataModel { 12 | var selection: UUID 13 | var shortcut: KeyboardShortcuts.Name 14 | } 15 | -------------------------------------------------------------------------------- /ScriptManager/Models/ScriptPresetModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScriptPresetModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 19.07.24. 6 | // 7 | 8 | struct ScriptPreset: Hashable { 9 | var title: String 10 | var icon: String 11 | var script: String 12 | var input: String? 13 | } 14 | -------------------------------------------------------------------------------- /ScriptManager/Models/UserdataModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserdataModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | struct Userdata: Codable { 9 | var scripts: [Script] 10 | var times: [ScriptTime] 11 | var tags: [Tag] 12 | var settings: Settings 13 | } 14 | -------------------------------------------------------------------------------- /ScriptManager/Utils/IconSize.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IconSize.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 10.02.23. 6 | // 7 | 8 | import Foundation 9 | 10 | struct IconSize { 11 | static let xs = 7.0 12 | static let s = 13.0 13 | static let m = 15.0 14 | static let l = 20.0 15 | } 16 | -------------------------------------------------------------------------------- /ScriptManager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/SettingsHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 15.05.24. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol SettingsHandlerProtocol { 11 | var settings: Settings { get set } 12 | 13 | func saveSettings() 14 | } 15 | -------------------------------------------------------------------------------- /ScriptManager/Models/ShortcutModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShortcutModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 21.03.23. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | struct Shortcut: Codable, Hashable { 12 | var shortcutIndex: Int 13 | var scriptId: UUID 14 | var keys: String 15 | } 16 | -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/StatusBarIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "StatusBarIcon.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "template-rendering-intent" : "template" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ScriptManager/Utils/Spacing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Spacing.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 03.02.23. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Spacing { 11 | static let zero = 0.0 12 | static let s = 2.0 13 | static let m = 5.0 14 | static let l = 10.0 15 | static let xl = 20.0 16 | static let xxl = 25.0 17 | } 18 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/NotificationHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 05.04.23. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol NotificationHandlerProtocol { 11 | static func sendResultNotification(state: Bool, name: String) 12 | static func sendStartNotification(name: String) 13 | } 14 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/HintHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HintHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | protocol HintHandlerProtocol { 9 | var hintVisible: Bool { get } 10 | var hintText: String { get } 11 | var hintType: HintType { get } 12 | 13 | func showHint(_ text: String, type: HintType) 14 | func hideHint() 15 | } 16 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/CronJobHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CronJobHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 29.07.24. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol CronJobHandlerProtocol { 11 | var cronJobs: [CronJob] { get } 12 | var interval: Double { get set } 13 | 14 | func start() 15 | func addJob(job: CronJob) 16 | func removeJob(id: UUID) 17 | } 18 | -------------------------------------------------------------------------------- /ScriptManager/Models/ResultModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResultModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 04.02.23. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Result { 11 | var output: String? 12 | var error: String? 13 | var state: ResultState 14 | } 15 | 16 | enum ResultState: Codable { 17 | case successfull 18 | case failed 19 | case interrupted 20 | case ready 21 | } 22 | -------------------------------------------------------------------------------- /ScriptManager/Models/CronJobModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CronJobModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 29.07.24. 6 | // 7 | 8 | import Foundation 9 | 10 | struct CronJob: Identifiable, Codable { 11 | var id = UUID() 12 | var interval: Interval 13 | var script: Script 14 | var lastExecutedDate: Date 15 | } 16 | 17 | public enum Interval: Codable { 18 | case DAILY 19 | case WEEKLY 20 | case MONTHLY 21 | } 22 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Signals/Danger.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.306", 9 | "green" : "0.252", 10 | "red" : "1.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Signals/Success.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.345", 9 | "green" : "0.732", 10 | "red" : "0.352" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Tag-Presets/Archive.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.933", 9 | "green" : "0.188", 10 | "red" : "0.369" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Tag-Presets/Favs.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.220", 9 | "green" : "0.816", 10 | "red" : "0.965" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Tag-Presets/Files.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.635", 9 | "green" : "0.584", 10 | "red" : "0.529" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Tag-Presets/Fixes.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.186", 9 | "green" : "0.138", 10 | "red" : "0.863" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Tag-Presets/GitLab.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.153", 9 | "green" : "0.427", 10 | "red" : "0.965" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/TagHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 28.03.24. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | protocol TagHandlerProtocol { 12 | var editMode: Bool { get set } 13 | var tags: [Tag] { get set } 14 | var selectedTag: UUID? { get set } 15 | var editTag: Tag { get set } 16 | var editColor: Color { get set } 17 | 18 | func saveTags() 19 | } 20 | -------------------------------------------------------------------------------- /ScriptManager/Models/ScriptTimeModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScriptTimeModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 16.02.24. 6 | // 7 | 8 | import Foundation 9 | 10 | struct ScriptTime: Codable { 11 | var lastTime: Int? 12 | var currentTime = 0 13 | var remainingTime: String? 14 | var progressValue = 1.0 15 | } 16 | 17 | let DefaultScriptTime = ScriptTime( 18 | lastTime: nil, 19 | currentTime: 0, 20 | remainingTime: nil, 21 | progressValue: 1.0 22 | ) 23 | -------------------------------------------------------------------------------- /ScriptManager/Models/TagModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 27.03.23. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | struct Tag: Identifiable, Codable { 12 | var id = UUID() 13 | var name: String 14 | var badgeColor: Data 15 | } 16 | 17 | let EmptyTag = Tag( 18 | id: UUID(uuidString: "6f7bcd9e-23dc-466c-85d3-4fc0ec5df5bb") ?? UUID(), 19 | name: "", 20 | badgeColor: ColorConverter.defaultEncodedColor 21 | ) 22 | -------------------------------------------------------------------------------- /ScriptManager/Extensions/ShortcutsExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShortcutExtension.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 28.03.24. 6 | // 7 | 8 | import Foundation 9 | import KeyboardShortcuts 10 | 11 | extension KeyboardShortcuts.Name { 12 | static let runScript1 = Self("runScript1") 13 | static let runScript2 = Self("runScript2") 14 | static let runScript3 = Self("runScript3") 15 | static let runScript4 = Self("runScript4") 16 | static let runScript5 = Self("runScript5") 17 | } 18 | -------------------------------------------------------------------------------- /ScriptManager/ViewModels/BackupViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BackupViewModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | import Resolver 9 | 10 | class BackupViewModel { 11 | @LazyInjected private var modalHandler: ModalHandlerProtocol 12 | private let backupProvider = BackupProvider() 13 | 14 | func exportUserdate() { 15 | backupProvider.exportUserdata() 16 | } 17 | 18 | func importUserdate() { 19 | backupProvider.importUserdata() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/ModalHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ModalHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 07.06.24. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol ModalHandlerProtocol { 11 | var modalVisible: Bool { get } 12 | var type: ModalType { get } 13 | 14 | func showModal(_ type: ModalType) 15 | func hideModal() 16 | } 17 | 18 | enum ModalType { 19 | case ADD_SCRIPT 20 | case EDIT_SCRIPT 21 | case ADD_TAG 22 | case EDIT_TAG 23 | case SETTINGS 24 | case INFO 25 | case ADD 26 | } 27 | -------------------------------------------------------------------------------- /ScriptManager/Handler/SettingsHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsHandler.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 15.05.24. 6 | // 7 | 8 | import Foundation 9 | import Resolver 10 | 11 | @Observable 12 | class SettingsHandler: SettingsHandlerProtocol { 13 | @LazyInjected @ObservationIgnored private var storageHandler: StorageHandlerProtocol 14 | 15 | var settings: Settings = DefaultSettings 16 | 17 | init() { 18 | settings = storageHandler.settings 19 | } 20 | 21 | func saveSettings() { 22 | storageHandler.settings = settings 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/StorageHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StorageHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 05.04.23. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol StorageHandlerProtocol { 11 | var firstLaunch: Bool { get set } 12 | var scripts: [Script] { get set } 13 | var tags: [Tag] { get set } 14 | var times: [ScriptTime] { get set } 15 | var settings: Settings { get set } 16 | var cronJobs: [CronJob] { get set } 17 | 18 | func resetData() 19 | func resetValues(_ key: StorageKeys) 20 | func setFirstLaunchToFalse() 21 | } 22 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/AlertHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 17.05.24. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol AlertHandlerProtocol { 11 | var alertVisible: Bool { get } 12 | var title: String { get } 13 | var message: String { get } 14 | var btnTitle: String { get } 15 | var cancelVisible: Bool { get } 16 | var action: () -> Void { get } 17 | 18 | func showAlert(title: String, message: String, btnTitle: String, cancelVisible: Bool?, action: @escaping () -> Void) 19 | func hideAlert() 20 | } 21 | -------------------------------------------------------------------------------- /ScriptManager/Models/ShellModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShellModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 06.02.23. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Shell: Identifiable, Codable, Hashable { 11 | var id: UUID = UUID() 12 | var type: ShellType 13 | var path: String 14 | var profile: String? 15 | } 16 | 17 | enum ShellType: String, Codable, Equatable { 18 | case zsh = "zsh" 19 | case bash = "bash" 20 | } 21 | 22 | let Shells: [Shell] = [ 23 | Shell(type: .zsh, path: "/bin/zsh", profile: "/.zshrc"), 24 | Shell(type: .bash, path: "/bin/bash", profile: "/.bash_profile") 25 | ] 26 | -------------------------------------------------------------------------------- /ScriptManager/Handler/ModalHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ModalHandler.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 06.06.24. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | @Observable 12 | class ModalHandler: ModalHandlerProtocol { 13 | var modalVisible: Bool = false 14 | var type: ModalType = .ADD_SCRIPT 15 | 16 | func showModal(_ type: ModalType) { 17 | self.type = type 18 | 19 | withAnimation { 20 | self.modalVisible = true 21 | } 22 | } 23 | 24 | func hideModal() { 25 | withAnimation { 26 | self.modalVisible = false 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ScriptManager/Presets/TagPreset.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagPreset.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | 9 | /// Presets for Tags to provide it to user 10 | let TagPresets: [TagPreset] = [ 11 | TagPreset(title: String(localized: "favorites"), color: AppColor.Favs, icon: "star"), 12 | TagPreset(title: String(localized: "archive"), color: AppColor.Archive, icon: "archivebox"), 13 | TagPreset(title: String(localized: "fixes"), color: AppColor.Fixes, icon: "hammer"), 14 | TagPreset(title: String(localized: "files"), color: AppColor.Files, icon: "doc.on.doc"), 15 | TagPreset(title: String(localized: "gitlab"), color: AppColor.GitLab, icon: "g.circle") 16 | ] 17 | -------------------------------------------------------------------------------- /ScriptManager/Utils/AppColor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorHandler.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 03.02.23. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | struct AppColor { 12 | static let Success = Color("Success") 13 | static let Danger = Color("Danger") 14 | static let Warning = Color("Warning") 15 | static let Creme = Color("Creme") 16 | static let Primary = Color("Primary") 17 | static let Secondary = Color("Secondary") 18 | 19 | // Tag-Presets 20 | static let Favs = Color("Favs") 21 | static let Archive = Color("Archive") 22 | static let Fixes = Color("Fixes") 23 | static let Files = Color("Files") 24 | static let GitLab = Color("GitLab") 25 | } 26 | -------------------------------------------------------------------------------- /Tests/Handler/TagHandlerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagHandlerTests.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 30.07.24. 6 | // 7 | 8 | @testable import ScriptManager 9 | 10 | import Resolver 11 | import Testing 12 | import Foundation 13 | 14 | final class TagHandlerTests { 15 | @LazyInjected private var sut: TagHandlerProtocol 16 | @LazyInjected private var storageHandler: StorageHandlerProtocol 17 | 18 | @Test("Save new tag") func saveTagTest() { 19 | let newTag = Tag(name: "", badgeColor: ColorConverter.defaultEncodedColor) 20 | 21 | storageHandler.tags.append(newTag) 22 | sut.saveTags() 23 | 24 | #expect(storageHandler.tags.first?.id == newTag.id) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ScriptManager/Protocols/ScriptHandlerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScriptHandlerProtocol.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 04.04.23. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol ScriptHandlerProtocol { 11 | var finishedCounter: Int { get set } 12 | 13 | var scripts: [Script] { get set } 14 | var editScript: Script { get set } 15 | var input: String { get set } 16 | 17 | var editMode: Bool { get set } 18 | var savedScripts: [Script] { get } 19 | var selectedIcon: Int { get set } 20 | var runningScript: [Script] { get set } 21 | 22 | func runScript(_ script: Script, test: Bool) async -> Result 23 | func interruptRunningProcess(scriptId: UUID) 24 | func saveScripts() 25 | } 26 | -------------------------------------------------------------------------------- /ScriptManager/Models/SettingsModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 06.02.23. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | struct Settings: Identifiable, Codable { 12 | var id = UUID() 13 | var shell: Shell 14 | var unicode: String 15 | var logs: Bool 16 | var pathLogs: String 17 | var notifications: Bool 18 | var mainColor: Data 19 | var shortcuts: [Shortcut] 20 | } 21 | 22 | let DefaultSettings = Settings( 23 | shell: Shell(type: .zsh, path: "/bin/zsh", profile: ""), 24 | unicode: "en_US.UTF-8", 25 | logs: false, 26 | pathLogs: "", 27 | notifications: false, 28 | mainColor: ColorConverter.defaultEncodedColor, 29 | shortcuts: [] 30 | ) 31 | -------------------------------------------------------------------------------- /ScriptManager/ViewModels/AlertViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertViewModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 17.05.24. 6 | // 7 | 8 | import Foundation 9 | import Resolver 10 | 11 | @Observable 12 | class AlertViewModel { 13 | @LazyInjected @ObservationIgnored private var alertHandler: AlertHandlerProtocol 14 | 15 | var title: String { 16 | alertHandler.title 17 | } 18 | 19 | var message: String { 20 | alertHandler.message 21 | } 22 | 23 | var btnTitle: String { 24 | alertHandler.btnTitle 25 | } 26 | 27 | var cancelVisible: Bool { 28 | alertHandler.cancelVisible 29 | } 30 | 31 | var action: () -> () { 32 | alertHandler.action 33 | } 34 | 35 | func hideAlert() { 36 | alertHandler.hideAlert() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ScriptManager/Views/Shortcuts/ShortcutView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShortcutView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 10.06.24. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ShortcutView: View { 11 | var shortcut: Shortcut 12 | 13 | var body: some View { 14 | HStack(spacing: 4) { 15 | ForEach(Array(shortcut.keys), id: \.self) { char in 16 | Text("\(String(char))") 17 | .font(.caption) 18 | .padding(.vertical, Spacing.s) 19 | .padding(.horizontal, Spacing.m) 20 | .background(.gray) 21 | .clipShape(RoundedRectangle(cornerRadius: 4.0)) 22 | } 23 | } 24 | } 25 | } 26 | 27 | #Preview { 28 | ShortcutView(shortcut: Shortcut(shortcutIndex: 0, scriptId: UUID(), keys: "CMD")) 29 | } 30 | -------------------------------------------------------------------------------- /Tests/Handler/SettingsHandlerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsHandlerTests.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 30.07.24. 6 | // 7 | 8 | @testable import ScriptManager 9 | 10 | import Resolver 11 | import Testing 12 | import Foundation 13 | 14 | final class SettingsHandlerTests { 15 | @LazyInjected private var sut: SettingsHandlerProtocol 16 | @LazyInjected private var storageHandler: StorageHandlerProtocol 17 | 18 | @Test("Save settings") func saveSettingsTest() { 19 | let newSettings = Settings(shell: Shell(type: .zsh, path: ""), unicode: "", logs: false, pathLogs: "", notifications: false, mainColor: ColorConverter.defaultEncodedColor, shortcuts: []) 20 | 21 | sut.settings = newSettings 22 | sut.saveSettings() 23 | #expect(storageHandler.settings.id == newSettings.id) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ScriptManager/Handler/TagHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagHandler.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 28.03.24. 6 | // 7 | 8 | import Foundation 9 | import Resolver 10 | import SwiftUI 11 | 12 | @Observable 13 | class TagHandler: TagHandlerProtocol { 14 | var editTag = Tag(name: "", badgeColor: ColorConverter.defaultEncodedColor) 15 | var editColor: Color = AppColor.Primary 16 | 17 | @LazyInjected @ObservationIgnored private var storageHandler: StorageHandlerProtocol 18 | 19 | var tags: [Tag] = [] { 20 | didSet { 21 | storageHandler.tags = tags 22 | } 23 | } 24 | 25 | var editMode: Bool = false 26 | var selectedTag: UUID? = nil 27 | 28 | init() { 29 | tags = storageHandler.tags 30 | } 31 | 32 | func saveTags() { 33 | storageHandler.tags = tags 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ScriptManager/ViewModels/HintViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HintViewModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | import Resolver 9 | 10 | class HintViewModel { 11 | @Injected var hintHandler: HintHandlerProtocol 12 | 13 | var hintType: HintType { 14 | hintHandler.hintType 15 | } 16 | 17 | var hintText: String { 18 | hintHandler.hintText 19 | } 20 | 21 | var icon: String { 22 | switch (hintType) { 23 | case .error: "xmark.circle.fill" 24 | case .warning: "exclamationmark.triangle.fill" 25 | case .success: "checkmark.seal.fill" 26 | } 27 | } 28 | 29 | func showHint(text: String, type: HintType) { 30 | hintHandler.showHint(text, type: type) 31 | } 32 | 33 | func hideHint() { 34 | hintHandler.hideHint() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Secondary.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.475", 9 | "green" : "0.741", 10 | "red" : "0.400" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.475", 27 | "green" : "0.741", 28 | "red" : "0.400" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ScriptManager/Views/Settings/SettingsAutostartView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsAutostartView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 17.03.23. 6 | // 7 | 8 | import SwiftUI 9 | import LaunchAtLogin 10 | 11 | struct SettingsAutostartView: View { 12 | var body: some View { 13 | VStack(alignment: .center) { 14 | HStack(alignment: .center) { 15 | Text("settings-autostart") 16 | .font(.subheadline) 17 | 18 | Spacer() 19 | 20 | LaunchAtLogin.Toggle("") 21 | .toggleStyle(.switch) 22 | } 23 | } 24 | .padding(.vertical, Spacing.m) 25 | .padding(.horizontal, Spacing.xl) 26 | } 27 | } 28 | 29 | struct SettingsAutostartView_Previews: PreviewProvider { 30 | static var previews: some View { 31 | SettingsAutostartView() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/Handler/ModalHandlerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ModalHandlerTests.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 30.07.24. 6 | // 7 | 8 | @testable import ScriptManager 9 | 10 | import Resolver 11 | import Testing 12 | 13 | final class ModalHandlerTests { 14 | @LazyInjected private var sut: ModalHandlerProtocol 15 | 16 | let testTitle = "a" 17 | let testMessage = "b" 18 | let testBtnTitle = "c" 19 | let testCancelVisible = false 20 | 21 | @Test("Check modal visible") func showModalTest() { 22 | sut.showModal(.INFO) 23 | #expect(sut.modalVisible == true) 24 | } 25 | 26 | @Test("Check modal hidden") func hideModalTest() { 27 | sut.hideModal() 28 | #expect(sut.modalVisible == false) 29 | } 30 | 31 | @Test("Check modal type") func modalTypeTest() { 32 | sut.showModal(.INFO) 33 | #expect(sut.type == .INFO) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ScriptManager/ViewModels/MainViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 17.05.24. 6 | // 7 | 8 | import Foundation 9 | import Resolver 10 | 11 | @Observable 12 | class MainViewModel { 13 | @LazyInjected @ObservationIgnored private var alertHandler: AlertHandlerProtocol 14 | @LazyInjected @ObservationIgnored private var modalHandler: ModalHandlerProtocol 15 | @LazyInjected @ObservationIgnored var scriptHandler: ScriptHandlerProtocol 16 | @LazyInjected @ObservationIgnored var hintHandler: HintHandlerProtocol 17 | 18 | var alertVisible: Bool { 19 | alertHandler.alertVisible 20 | } 21 | 22 | var modalVisible: Bool { 23 | modalHandler.modalVisible 24 | } 25 | 26 | var hintVisible: Bool { 27 | hintHandler.hintVisible 28 | } 29 | 30 | var modalType: ModalType { 31 | modalHandler.type 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/Handler/HintHandlerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HintHandlerTests.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 30.07.24. 6 | // 7 | 8 | @testable import ScriptManager 9 | 10 | import Resolver 11 | import Testing 12 | 13 | @Suite(.serialized) final class HintHandlerTests { 14 | @LazyInjected private var sut: HintHandlerProtocol 15 | 16 | let testMessage = "a" 17 | 18 | @Test("Check hint visible") func showHintTest() { 19 | sut.showHint(testMessage, type: .success) 20 | #expect(sut.hintVisible == true) 21 | } 22 | 23 | @Test("Check hint hidden") func hideHintTest() { 24 | sut.hideHint() 25 | #expect(sut.hintVisible == false) 26 | } 27 | 28 | @Test("Check hint values") func hintValuesTest() { 29 | sut.showHint(testMessage, type: .error) 30 | #expect(sut.hintText == testMessage) 31 | #expect(sut.hintType == .error) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ScriptManager/Views/Scripts/AddScript/TagPickerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagPickerView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 27.03.23. 6 | // 7 | 8 | import Resolver 9 | import SwiftUI 10 | 11 | struct TagPickerView: View { 12 | @Injected private var tagHandler: TagHandlerProtocol 13 | @State private var vm = ScriptViewModel() 14 | 15 | var body: some View { 16 | Picker("", selection: $vm.scriptHandler.editScript.tagID) { 17 | // Add empty default selection 18 | Text(EmptyTag.name) 19 | .tag(EmptyTag.id) 20 | 21 | ForEach(tagHandler.tags) { tag in 22 | Text(tag.name) 23 | .tag(tag.id) 24 | } 25 | } 26 | .frame(width: 185) 27 | } 28 | } 29 | 30 | struct TagPickerView_Previews: PreviewProvider { 31 | static var previews: some View { 32 | TagPickerView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ScriptManager/Views/Settings/SettingsUnicodeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsUnicodeView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 10.02.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SettingsUnicodeView: View { 11 | @Binding var vm: SettingsViewModel 12 | 13 | var body: some View { 14 | VStack(alignment: .leading) { 15 | HStack(alignment: .center) { 16 | Text("shell-unicode") 17 | .font(.caption) 18 | 19 | Spacer() 20 | 21 | TextField("", text: $vm.tempSettings.unicode) 22 | .frame(width: 150) 23 | } 24 | } 25 | .padding(.vertical, Spacing.m) 26 | } 27 | } 28 | 29 | struct SettingsUnicodeView_Previews: PreviewProvider { 30 | static var previews: some View { 31 | SettingsUnicodeView(vm: .constant(SettingsViewModel())) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ScriptManager/Handler/HintHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HintHandler.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | @Observable 12 | class HintHandler: HintHandlerProtocol { 13 | let interval = 3.0 14 | var hintVisible: Bool = false 15 | var hintText: String = "Test-Hint" 16 | var hintType: HintType = .warning 17 | 18 | func showHint(_ text: String, type: HintType) { 19 | hintText = text 20 | hintType = type 21 | 22 | withAnimation { 23 | self.hintVisible = true 24 | } 25 | 26 | DispatchQueue.main.asyncAfter(deadline: .now() + interval) { 27 | self.hideHint() 28 | } 29 | } 30 | 31 | func hideHint() { 32 | withAnimation { 33 | self.hintVisible = false 34 | } 35 | } 36 | } 37 | 38 | public enum HintType { 39 | case warning 40 | case error 41 | case success 42 | } 43 | -------------------------------------------------------------------------------- /ScriptManager/Views/Scripts/ScriptRow/ScriptRowActions/ScriptDeleteButtonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScriptDeleteButtonView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 10.02.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ScriptDeleteButtonView: View { 11 | @State private var vm = ScriptViewModel() 12 | var scriptId: UUID 13 | var disabled: Bool 14 | 15 | var body: some View { 16 | Button { 17 | vm.showDeleteScriptAlert(id: scriptId) 18 | } label: { 19 | Image(systemName: "trash") 20 | .resizable() 21 | .frame(width: IconSize.s, height: IconSize.s) 22 | .padding(Spacing.l) 23 | } 24 | .buttonStyle(.plain) 25 | .disabled(disabled) 26 | .help("button-delete") 27 | } 28 | } 29 | 30 | struct ScriptDeleteButtonView_Previews: PreviewProvider { 31 | static var previews: some View { 32 | ScriptDeleteButtonView(scriptId: UUID(), disabled: false) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ScriptManager/Views/Scripts/ScriptRow/ScriptRowActions/ScriptDetailButtonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScriptDetailButtonView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 01.04.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ScriptDetailButtonView: View { 11 | var onClick: () -> Void 12 | var icon: String 13 | var disabled: Bool 14 | var help: LocalizedStringKey 15 | 16 | var body: some View { 17 | Button { 18 | onClick() 19 | } label: { 20 | Image(systemName: icon) 21 | .resizable() 22 | .frame(width: IconSize.s, height: IconSize.s) 23 | .padding(Spacing.l) 24 | } 25 | .buttonStyle(.plain) 26 | .disabled(disabled) 27 | .help(help) 28 | } 29 | } 30 | 31 | struct ScriptDetailButtonView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | ScriptDetailButtonView(onClick: {}, icon: "xmark", disabled: false, help: "Preview") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ScriptManager/ViewModels/ModalViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ModalViewModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 07.06.24. 6 | // 7 | 8 | import Foundation 9 | import Resolver 10 | 11 | @Observable 12 | class ModalViewModel { 13 | @Injected @ObservationIgnored var modalHandler: ModalHandlerProtocol 14 | 15 | var modalType: ModalType { 16 | modalHandler.type 17 | } 18 | 19 | var modalTitle: String { 20 | switch modalHandler.type { 21 | case .ADD_SCRIPT: 22 | String(localized: "add-new-script") 23 | case .EDIT_SCRIPT: 24 | String(localized: "edit-script-title") 25 | case .ADD_TAG: 26 | String(localized: "add-new-tag") 27 | case .SETTINGS: 28 | String(localized: "settings") 29 | case .INFO: 30 | String(localized: "info") 31 | case .ADD: 32 | String(localized: "add") 33 | case .EDIT_TAG: 34 | String(localized: "edit-tag-title") 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ScriptManager/Handler/AlertHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertHandler.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 17.05.24. 6 | // 7 | 8 | import Foundation 9 | import Resolver 10 | import SwiftUI 11 | 12 | @Observable 13 | class AlertHandler: AlertHandlerProtocol { 14 | var alertVisible: Bool = false 15 | 16 | var title: String = "" 17 | var message: String = "" 18 | var btnTitle: String = "" 19 | var action: () -> Void = {} 20 | var cancelVisible: Bool = true 21 | 22 | func showAlert(title: String, message: String, btnTitle: String, cancelVisible: Bool? = true, action: @escaping () -> Void) { 23 | self.title = title 24 | self.message = message 25 | self.btnTitle = btnTitle 26 | self.action = action 27 | self.cancelVisible = cancelVisible ?? true 28 | 29 | withAnimation { 30 | self.alertVisible = true 31 | } 32 | } 33 | 34 | func hideAlert() { 35 | withAnimation { 36 | self.alertVisible = false 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ScriptManager/Views/Scripts/AddScript/IconPickerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IconPickerView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.02.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct IconPickerView: View { 11 | @State private var vm = ScriptViewModel() 12 | 13 | var body: some View { 14 | Form { 15 | Picker(selection: $vm.scriptHandler.selectedIcon, label: EmptyView()) { 16 | Section(header: Text("Icons")) { 17 | ForEach(ScriptIcons.indices, id: \.self) { (i) in 18 | HStack { 19 | Image(systemName: ScriptIcons[i]) 20 | } 21 | .tag(i) 22 | } 23 | } 24 | } 25 | .multilineTextAlignment(.leading) 26 | .frame(maxWidth: 60) 27 | .padding(.leading, -8) 28 | } 29 | } 30 | } 31 | 32 | struct IconPickerView_Previews: PreviewProvider { 33 | static var previews: some View { 34 | IconPickerView() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ScriptManager/Extensions/DateExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DateExtension.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 28.03.24. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Date { 11 | /// Convert Date to formatted String 12 | /// - Returns: formatted date as `String` 13 | func toFormattedDate() -> String { 14 | let dateFormatter = DateFormatter() 15 | dateFormatter.dateFormat = "dd.MM.yy HH:mm:ss" 16 | 17 | return dateFormatter.string(from: self) 18 | } 19 | 20 | /// Get String for date with local formatting 21 | /// - Returns: String for date `ddMMyyyy` 22 | func toDateString() -> String { 23 | let customFormat = "ddMMyyyy" 24 | 25 | let localeFormat = DateFormatter.dateFormat(fromTemplate: customFormat, options: 0, locale: Locale.current) 26 | let formatter = DateFormatter() 27 | formatter.dateFormat = localeFormat 28 | formatter.timeZone = TimeZone(secondsFromGMT: 0) 29 | 30 | let dateString = formatter.string(from: self) 31 | return dateString 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 DanielFiller30 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ScriptManager/Extensions/IntervalExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntervalExtension.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 29.07.24. 6 | // 7 | 8 | import Foundation 9 | 10 | public extension Interval { 11 | func checkDiff(lastExecuted: Date) -> Bool { 12 | let calendar = Calendar.current 13 | var check: ComparisonResult 14 | 15 | switch self { 16 | case .DAILY: 17 | let oneDay = calendar.date(byAdding: .day, value: 1, to: lastExecuted)! 18 | check = calendar.compare(.now, to: oneDay, toGranularity: .day) 19 | case .WEEKLY: 20 | let oneWeek = calendar.date(byAdding: .weekOfYear, value: 1, to: lastExecuted)! 21 | check = calendar.compare(.now, to: oneWeek, toGranularity: .day) 22 | case .MONTHLY: 23 | let oneMonth = calendar.date(byAdding: .month, value: 1, to: lastExecuted)! 24 | check = calendar.compare(.now, to: oneMonth, toGranularity: .day) 25 | } 26 | 27 | if check == .orderedSame || check == .orderedDescending { 28 | return true 29 | } else { 30 | return false 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Media/StatusBarIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ScriptManager/Models/ScriptModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScriptModel.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 03.02.23. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Script: Identifiable, Codable { 11 | var id = UUID() 12 | var name: String 13 | var icon: String 14 | var command: String 15 | var success: ResultState 16 | var finished: Bool 17 | var lastRun: Date? 18 | var tagID: UUID = EmptyTag.id 19 | var time: ScriptTime? 20 | var input: String? 21 | var output: String? 22 | var error: String? 23 | } 24 | 25 | let EmptyScript = Script( 26 | id: UUID(uuidString: "8ac5590d-68cf-48c6-83da-4a886f26f528") ?? UUID(), 27 | name: "", 28 | icon: "applescript", 29 | command: "cd /Desktop/ sh..", 30 | success: .ready, 31 | finished: false, 32 | lastRun: Date.now, 33 | tagID: EmptyTag.id, 34 | time: DefaultScriptTime, 35 | input: "", 36 | output: "", 37 | error: "" 38 | ) 39 | 40 | let DefaultScript = Script( 41 | name: "Test", 42 | icon: "terminal", 43 | command: "/test", 44 | success: .ready, 45 | finished: false, 46 | time: DefaultScriptTime, 47 | input: "", 48 | output: "", 49 | error: "" 50 | ) 51 | -------------------------------------------------------------------------------- /ScriptManager/Storage/StorageHandlerMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StorageHandlerMock.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 30.07.24. 6 | // 7 | 8 | class StorageHandlerMock: StorageHandlerProtocol { 9 | var firstLaunch = false { didSet { 10 | print("Storage -- FirstLaunch set") 11 | }} 12 | 13 | var scripts: [Script] = [] { didSet { 14 | print("Storage -- Scripts set") 15 | }} 16 | 17 | var tags: [Tag] = [] { didSet { 18 | print("Storage -- Tags set") 19 | }} 20 | 21 | var times: [ScriptTime] = [] { didSet { 22 | print("Storage -- Times set") 23 | }} 24 | 25 | var settings: Settings = DefaultSettings { didSet { 26 | print("Storage -- Settings set") 27 | }} 28 | 29 | var cronJobs: [CronJob] = [] { didSet { 30 | print("Storage -- CronJobs set") 31 | }} 32 | 33 | func resetData() { 34 | print("Storage -- Reset data executed") 35 | } 36 | 37 | func resetValues(_ key: StorageKeys) { 38 | print("Storage -- Reset values executed for key: \(key)") 39 | } 40 | 41 | func setFirstLaunchToFalse() { 42 | print("Storage -- Toggled first launch") 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/StatusBarIcon.imageset/StatusBarIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ScriptManager/Storage/StorageWrapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StorageWrapper.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 28.03.24. 6 | // 7 | 8 | import Foundation 9 | 10 | @propertyWrapper 11 | struct Storage { 12 | private let key: StorageKeys 13 | private let defaultValue: T 14 | 15 | init(key: StorageKeys, defaultValue: T) { 16 | self.key = key 17 | self.defaultValue = defaultValue 18 | } 19 | 20 | var wrappedValue: T { 21 | get { 22 | // Read value from UserDefaults 23 | guard let data = UserDefaults.standard.object(forKey: key.rawValue) as? Data else { 24 | // Return defaultValue when no data in UserDefaults 25 | return defaultValue 26 | } 27 | 28 | // Convert data to the desire data type 29 | let value = try? JSONDecoder().decode(T.self, from: data) 30 | return value ?? defaultValue 31 | } 32 | set { 33 | // Convert newValue to data 34 | let data = try? JSONEncoder().encode(newValue) 35 | 36 | // Set value to UserDefaults 37 | UserDefaults.standard.set(data, forKey: key.rawValue) 38 | } 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /Tests/Handler/AlertHandlerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertHandlerTests.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 30.07.24. 6 | // 7 | 8 | @testable import ScriptManager 9 | 10 | import Resolver 11 | import Testing 12 | 13 | @Suite(.serialized) final class AlertHandlerTests { 14 | @LazyInjected private var sut: AlertHandlerProtocol 15 | 16 | let testTitle = "a" 17 | let testMessage = "b" 18 | let testBtnTitle = "c" 19 | let testCancelVisible = false 20 | 21 | @Test("Check alert visible") func showAlertTest() { 22 | sut.showAlert(title: testTitle, message: testMessage, btnTitle: testBtnTitle, cancelVisible: testCancelVisible, action: {}) 23 | #expect(sut.alertVisible == true) 24 | } 25 | 26 | @Test("Check alert hidden") func hideAlertTest() { 27 | sut.hideAlert() 28 | #expect(sut.alertVisible == false) 29 | } 30 | 31 | @Test("Check alert values") func alertValuesTest() { 32 | sut.showAlert(title: testTitle, message: testMessage, btnTitle: testBtnTitle, cancelVisible: testCancelVisible, action: {}) 33 | #expect(sut.title == testTitle) 34 | #expect(sut.message == testMessage) 35 | #expect(sut.btnTitle == testBtnTitle) 36 | #expect(sut.cancelVisible == testCancelVisible) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ScriptManager/Views/Settings/SettingsNotificationsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsNotificationsView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 10.02.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SettingsNotificationsView: View { 11 | @Binding var vm: SettingsViewModel 12 | 13 | var body: some View { 14 | VStack(alignment: .center) { 15 | HStack(alignment: .center) { 16 | Text("settings-notifications") 17 | .font(.subheadline) 18 | 19 | HelpView(title: "hint-notifications-title", text: "hint-notifications-text") 20 | 21 | Spacer() 22 | 23 | Toggle("", isOn: $vm.tempSettings.notifications) 24 | .toggleStyle(.switch) 25 | .onChange(of: vm.tempSettings.notifications) { _,_ in 26 | vm.activateNotifications() 27 | } 28 | 29 | } 30 | } 31 | .padding(.vertical, Spacing.m) 32 | .padding(.horizontal, Spacing.xl) 33 | } 34 | } 35 | 36 | struct SettingsNotificationsView_Previews: PreviewProvider { 37 | static var previews: some View { 38 | SettingsNotificationsView(vm: .constant(SettingsViewModel())) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Primary.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.824", 9 | "green" : "0.624", 10 | "red" : "0.490" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "light" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.824", 27 | "green" : "0.624", 28 | "red" : "0.490" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | }, 33 | { 34 | "appearances" : [ 35 | { 36 | "appearance" : "luminosity", 37 | "value" : "dark" 38 | } 39 | ], 40 | "color" : { 41 | "color-space" : "srgb", 42 | "components" : { 43 | "alpha" : "1.000", 44 | "blue" : "0.825", 45 | "green" : "0.623", 46 | "red" : "0.492" 47 | } 48 | }, 49 | "idiom" : "universal" 50 | } 51 | ], 52 | "info" : { 53 | "author" : "xcode", 54 | "version" : 1 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Creme.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.929", 9 | "green" : "0.929", 10 | "red" : "0.929" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "light" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.082", 27 | "green" : "0.082", 28 | "red" : "0.082" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | }, 33 | { 34 | "appearances" : [ 35 | { 36 | "appearance" : "luminosity", 37 | "value" : "dark" 38 | } 39 | ], 40 | "color" : { 41 | "color-space" : "display-p3", 42 | "components" : { 43 | "alpha" : "1.000", 44 | "blue" : "0.577", 45 | "green" : "0.577", 46 | "red" : "0.577" 47 | } 48 | }, 49 | "idiom" : "universal" 50 | } 51 | ], 52 | "info" : { 53 | "author" : "xcode", 54 | "version" : 1 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ScriptManager/Colors.xcassets/Signals/Warning.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.267", 9 | "green" : "0.600", 10 | "red" : "1.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "light" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.267", 27 | "green" : "0.600", 28 | "red" : "1.000" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | }, 33 | { 34 | "appearances" : [ 35 | { 36 | "appearance" : "luminosity", 37 | "value" : "dark" 38 | } 39 | ], 40 | "color" : { 41 | "color-space" : "srgb", 42 | "components" : { 43 | "alpha" : "1.000", 44 | "blue" : "0.267", 45 | "green" : "0.600", 46 | "red" : "1.000" 47 | } 48 | }, 49 | "idiom" : "universal" 50 | } 51 | ], 52 | "info" : { 53 | "author" : "xcode", 54 | "version" : 1 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ScriptManager/Views/Common/CustomButtonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomButtonView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 31.03.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CustomButtonView: View { 11 | var onClick: () -> Void 12 | var label: LocalizedStringKey 13 | var color: AnyShapeStyle 14 | var outlined: Bool 15 | var disabled: Bool 16 | 17 | var body: some View { 18 | Button { 19 | onClick() 20 | } label: { 21 | HStack(alignment: .center) { 22 | Text(label) 23 | .foregroundColor(.white) 24 | } 25 | .frame(maxWidth: .infinity) 26 | .padding(Spacing.l) 27 | .background(outlined ? AnyShapeStyle(.ultraThinMaterial) : color) 28 | .cornerRadius(10.0) 29 | .overlay( 30 | RoundedRectangle(cornerRadius: 10.0) 31 | .stroke(color, lineWidth: outlined ? 1 : 0) 32 | ) 33 | 34 | } 35 | .buttonStyle(.plain) 36 | .disabled(disabled) 37 | } 38 | } 39 | 40 | struct CustomButtonView_Previews: PreviewProvider { 41 | static var previews: some View { 42 | CustomButtonView(onClick: {}, label: "", color: AnyShapeStyle(.black), outlined: false, disabled: false) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ScriptManager/Views/Scripts/ScriptRow/ScriptRowView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScriptRowView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 05.02.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ScriptRowView: View { 11 | @State var vm = ScriptViewModel() 12 | @State var showDetails: Bool = false 13 | 14 | @Binding var showAddScriptModal: Bool 15 | 16 | var script: Script 17 | 18 | var body: some View { 19 | ZStack { 20 | DisclosureGroup(isExpanded: $showDetails) { 21 | VStack { 22 | ScriptDetailsView(showAddScriptModal: $showAddScriptModal, script: script) 23 | } 24 | .padding(.all, Spacing.l) 25 | 26 | } label: { 27 | ScriptRowLabel( 28 | toggleDetails: { 29 | withAnimation() { 30 | showDetails.toggle() 31 | } 32 | }, 33 | script: script 34 | ) 35 | } 36 | .padding(.all, Spacing.l) 37 | .background(.thickMaterial) 38 | .cornerRadius(15) 39 | .shadow(radius: 3, x: 1, y: 2) 40 | } 41 | } 42 | } 43 | 44 | struct ScriptRowView_Previews: PreviewProvider { 45 | static var previews: some View { 46 | ScriptRowView(showAddScriptModal: .constant(false), script: DefaultScript) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ScriptManager/Views/MainView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 03.02.23. 6 | // 7 | 8 | import SwiftUI 9 | import ConfettiSwiftUI 10 | 11 | struct MainView: View { 12 | @State private var vm = MainViewModel() 13 | 14 | var body: some View { 15 | ZStack { 16 | VStack(spacing: Spacing.zero) { 17 | HeaderView() 18 | 19 | Divider() 20 | .frame(minHeight: 2) 21 | 22 | ScriptsListView() 23 | .padding(.top, Spacing.l) 24 | } 25 | 26 | if vm.alertVisible { 27 | AlertView() 28 | } 29 | 30 | if vm.modalVisible { 31 | ModalView() 32 | } 33 | 34 | if vm.hintVisible { 35 | HintView() 36 | .position(x: 380 / 2, y: 50) 37 | } 38 | } 39 | .frame(width: 380, height: 550) 40 | .background(.ultraThinMaterial) 41 | .confettiCannon( 42 | counter: $vm.scriptHandler.finishedCounter, 43 | num: 80, 44 | colors: [Color(.primary), Color(.secondary)], 45 | confettiSize: 10, 46 | radius: 350 47 | ) 48 | } 49 | } 50 | 51 | struct MainView_Previews: PreviewProvider { 52 | static var previews: some View { 53 | MainView() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ScriptManager.xcodeproj/xcuserdata/Daniel.Filler.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AnyCodable (Playground) 1.xcscheme 8 | 9 | isShown 10 | 11 | orderHint 12 | 4 13 | 14 | AnyCodable (Playground) 2.xcscheme 15 | 16 | isShown 17 | 18 | orderHint 19 | 5 20 | 21 | AnyCodable (Playground).xcscheme 22 | 23 | isShown 24 | 25 | orderHint 26 | 3 27 | 28 | ScriptManager.xcscheme_^#shared#^_ 29 | 30 | orderHint 31 | 0 32 | 33 | ScriptManagerTests.xcscheme_^#shared#^_ 34 | 35 | orderHint 36 | 4 37 | 38 | Tests.xcscheme_^#shared#^_ 39 | 40 | orderHint 41 | 4 42 | 43 | 44 | SuppressBuildableAutocreation 45 | 46 | DC0448F1298D2F38004B6389 47 | 48 | primary 49 | 50 | 51 | DCDD16AB2C57D5F700757547 52 | 53 | primary 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /ScriptManager/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "logo_16 (1).png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "logo_32.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "logo_32 1.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "logo_64.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "logo_128.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "logo_256 1.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "logo_256.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "logo_512.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "logo_512 1.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "logo_1024.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /ScriptManager/Views/Common/HelpView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HelpView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 10.02.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct HelpView: View { 11 | var title: LocalizedStringKey 12 | var text: LocalizedStringKey 13 | 14 | @State var showHint: Bool = false 15 | 16 | var body: some View { 17 | Button { 18 | showHint.toggle() 19 | } label: { 20 | Image(systemName: "questionmark.square.dashed") 21 | .resizable() 22 | .frame(width: IconSize.m, height: IconSize.m) 23 | } 24 | .buttonStyle(.plain) 25 | .popover(isPresented: $showHint) { 26 | VStack(alignment: .center) { 27 | Text(title) 28 | .font(.headline) 29 | .multilineTextAlignment(.center) 30 | .padding(.bottom, Spacing.l) 31 | .padding(.top, Spacing.xl) 32 | 33 | Divider() 34 | 35 | Text(text) 36 | .font(.caption) 37 | .multilineTextAlignment(.center) 38 | .lineLimit(10) 39 | .padding(Spacing.l) 40 | 41 | Spacer() 42 | 43 | } 44 | .frame(maxWidth: 200, minHeight: 200) 45 | } 46 | } 47 | } 48 | 49 | struct HintView_Previews: PreviewProvider { 50 | static var previews: some View { 51 | HelpView(title: "Test", text: "Info text") 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ScriptManager/Provider/JSONProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSONProvider.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | import Foundation 9 | import Resolver 10 | 11 | class JSONProvider { 12 | @LazyInjected var storageHandler: StorageHandlerProtocol 13 | 14 | /// Convert saved userdata to json string 15 | /// - Returns: json-object as `String` 16 | func convertToJson() -> String? { 17 | let savedUserdata = Userdata( 18 | scripts: storageHandler.scripts, 19 | times: storageHandler.times, 20 | tags: storageHandler.tags, 21 | settings: storageHandler.settings 22 | ) 23 | 24 | let jsonEncoder = JSONEncoder() 25 | 26 | do { 27 | let jsonData = try jsonEncoder.encode(savedUserdata) 28 | guard let json = String(data: jsonData, encoding: String.Encoding.utf8) else { 29 | return nil 30 | } 31 | 32 | return json 33 | } catch { 34 | debugPrint(error) 35 | return nil 36 | } 37 | } 38 | 39 | /// Decode json string to userdata model 40 | /// - Parameter data: The imported data of json file 41 | /// - Returns: The userdata object 42 | func decodeToObject(data: Data) -> Userdata? { 43 | do { 44 | let jsonDecoder = JSONDecoder() 45 | let userdata = try jsonDecoder.decode(Userdata.self, from: data) 46 | return userdata 47 | } catch { 48 | debugPrint(error) 49 | return nil 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ScriptManager/Views/Common/BadgeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BadgeView.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 22.03.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BadgeView: View { 11 | @State private var vm = TagViewModel() 12 | 13 | var color: Color 14 | var title: String 15 | var active: Bool 16 | var outlined: Bool? 17 | 18 | var body: some View { 19 | HStack(alignment: .center) { 20 | HStack { 21 | Text(title) 22 | .font(.caption) 23 | .fontWeight(.light) 24 | .lineLimit(1) 25 | .foregroundColor(active ? .black : nil) 26 | 27 | Circle() 28 | .frame(maxWidth: 10, maxHeight: 10) 29 | .foregroundColor(color) 30 | } 31 | .padding(.horizontal, Spacing.l) 32 | .padding(.vertical, 7.0) 33 | .background(active ? AnyShapeStyle(.white) : AnyShapeStyle(.ultraThinMaterial)) 34 | .overlay( 35 | RoundedRectangle(cornerRadius: 12.0) 36 | .stroke(outlined ?? true ? color : .clear, lineWidth: 1.5) 37 | ) 38 | .shadow(radius: 3, x: 1, y: 2) 39 | .cornerRadius(12.0) 40 | .help(title) 41 | } 42 | .frame(maxWidth: 100) 43 | } 44 | } 45 | 46 | struct BadgeView_Previews: PreviewProvider { 47 | static var previews: some View { 48 | VStack { 49 | BadgeView(color: AppColor.Primary, title: "Kurz", active: false) 50 | } 51 | .padding() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ScriptManager/Presets/ScriptPresets.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScriptPresets.swift 3 | // ScriptManager 4 | // 5 | // Created by Filler, Daniel on 20.07.24. 6 | // 7 | 8 | /// Presets for Scripts to provide it to user 9 | let ScriptPresets: [ScriptPreset] = [ 10 | ScriptPreset(title: String(localized: "open-file"), icon: "doc.richtext", script: "open ;"), 11 | ScriptPreset(title: String(localized: "say-name"), icon: "waveform", script: "say ;"), 12 | ScriptPreset(title: String(localized: "clean-desktop"), icon: "wand.and.stars", script: "desktop_path=\"$HOME/Desktop\"; mkdir -p \"$desktop_path/Documents\" \"$desktop_path/Pictures\" \"$desktop_path/Videos\" \"$desktop_path/Other\"; for file in \"$desktop_path\"/*; do if [[ -f \"$file\" ]]; then extension=\"${file##*.}\"; case \"$extension\" in doc|rtf|docx|txt|pdf|xlsx) mv \"$file\" \"$desktop_path/Documents\"; ;; jpg|jpeg|png|gif|bmp) mv \"$file\" \"$desktop_path/Pictures\"; ;; mp4|avi|mkv|mov) mv \"$file\" \"$desktop_path/Videos\"; ;; *) mv \"$file\" \"$desktop_path/Other\"; ;; esac; fi; done; echo \"Files on your desktop have been sorted into folders.\""), 13 | ScriptPreset(title: String(localized: "countdown"), icon: "clock.arrow.circlepath", script: "sleep