diff --git a/Images/.DS_Store b/Images/.DS_Store new file mode 100644 index 0000000..e41069a Binary files /dev/null and b/Images/.DS_Store differ diff --git a/Images/iOS/Journal.it iOS Audio.png b/Images/iOS/Journal.it iOS Audio.png new file mode 100644 index 0000000..8ec3e8f Binary files /dev/null and b/Images/iOS/Journal.it iOS Audio.png differ diff --git a/Images/iOS/Journal.it iOS Camera.png b/Images/iOS/Journal.it iOS Camera.png new file mode 100644 index 0000000..9811334 Binary files /dev/null and b/Images/iOS/Journal.it iOS Camera.png differ diff --git a/Images/iOS/Journal.it iOS Notes.png b/Images/iOS/Journal.it iOS Notes.png new file mode 100644 index 0000000..0f61f4b Binary files /dev/null and b/Images/iOS/Journal.it iOS Notes.png differ diff --git a/README.md b/README.md index 2d90df4..93e3983 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,39 @@ # Journal.it **About** -This is a SwiftUI app that allows you to quickly get down information that you need, quickly. It includes a text editor, voice recorder and a simple camera. All the documents can be stored in the app and have the option to be exported if needed. +This Is A SwiftUI App That Allows You To Quickly Get Down Information That You Need, Quickly. It Includes A Text Editor, Audio Recorder And A Simple Camera. The Notes Document Can Be Stored In The App And Has The Option To Be Exported If Needed. Recording Can Be Accessed Through The Files App And Photos Can Be Accessed Through The Photos App. -# Features +## **Releases** - - Ability to take photos - - Ability to make notes - - Ability to record audio - - Ability to share files outside of the app +[Click Here...]() -# Releases +## **Features** -Stay Tuned... + - Take Photos + - Make Notes + - Record Audio + - Share Files Outside Of The App -# Features To Come +## **Features To Be Implemented** - Light Photo Editing - Recording Editing - - Audio to text conversion + - Audio To Text Conversion - A macOS App - -# Things To Note - -This is not a fully fledged version of any of the core features in the app. It is designed to be a quick and light all-in-one solution. It is not designed for heavy usage all the time, and the features here probably won’t stand up to those use cases. However, proper apps for each of these core features could be considered in the future. - -# Images -Stay Tuned... + + ## **Images** + + [Click Here...]() + +## **Things To Note** + + 1. This Project Is Free To Be Added To By The Community, If You Wish To Help, File A Issue With The Enhancement Tag + 2. Any And All Feedback Will Be Helpful For Future Development + 3. If You Wish To Report A Bug, Please Use Either The Feedback Button In The App Or Use GitHub Issues + + ## **Credits** + + Thanks To These People Who Developed These Packages, Who Without This Project Would Not Be Possible: + + - danielsaidi [SwiftUIKit](https://github.com/danielsaidi/SwiftUIKit) + - kyle-n [HighlightedTextEditor](https://github.com/kyle-n/HighlightedTextEditor) diff --git a/Source Code/Journal.it/Journal-it-Info.plist b/Source Code/Journal.it/Journal-it-Info.plist new file mode 100644 index 0000000..ff579a6 --- /dev/null +++ b/Source Code/Journal.it/Journal-it-Info.plist @@ -0,0 +1,8 @@ + + + + + UIFileSharingEnabled + + + diff --git a/Source Code/Journal.it/Journal.it.xcodeproj/project.pbxproj b/Source Code/Journal.it/Journal.it.xcodeproj/project.pbxproj new file mode 100644 index 0000000..cdb9dce --- /dev/null +++ b/Source Code/Journal.it/Journal.it.xcodeproj/project.pbxproj @@ -0,0 +1,454 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + D512A46827AAFB5D00057524 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A46727AAFB5D00057524 /* SettingsView.swift */; }; + D512A46A27AAFC9C00057524 /* Notes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A46927AAFC9C00057524 /* Notes.swift */; }; + D512A46C27AAFCA400057524 /* Audio.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A46B27AAFCA400057524 /* Audio.swift */; }; + D512A46E27AAFCAB00057524 /* Camera.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A46D27AAFCAB00057524 /* Camera.swift */; }; + D512A47127AAFD3A00057524 /* HighlightedTextEditor in Frameworks */ = {isa = PBXBuildFile; productRef = D512A47027AAFD3A00057524 /* HighlightedTextEditor */; }; + D512A47427AB076A00057524 /* SwiftUIKit in Frameworks */ = {isa = PBXBuildFile; productRef = D512A47327AB076A00057524 /* SwiftUIKit */; }; + D512A47727AB1FAA00057524 /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A47627AB1FAA00057524 /* AudioPlayer.swift */; }; + D512A47927AB1FE500057524 /* AudioRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A47827AB1FE500057524 /* AudioRecorder.swift */; }; + D512A47B27AB202400057524 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A47A27AB202400057524 /* Extensions.swift */; }; + D512A47D27AB205400057524 /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A47C27AB205400057524 /* Helper.swift */; }; + D512A47F27AB207D00057524 /* RecordingDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A47E27AB207D00057524 /* RecordingDataModel.swift */; }; + D512A48127AB20CB00057524 /* RecordingsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512A48027AB20CB00057524 /* RecordingsList.swift */; }; + D5B24D9127A9CB61006CCCF9 /* Journal_itApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B24D9027A9CB61006CCCF9 /* Journal_itApp.swift */; }; + D5B24D9327A9CB61006CCCF9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B24D9227A9CB61006CCCF9 /* ContentView.swift */; }; + D5B24D9527A9CB64006CCCF9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D5B24D9427A9CB64006CCCF9 /* Assets.xcassets */; }; + D5B24D9827A9CB64006CCCF9 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D5B24D9727A9CB64006CCCF9 /* Preview Assets.xcassets */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + D512A46727AAFB5D00057524 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; + D512A46927AAFC9C00057524 /* Notes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notes.swift; sourceTree = ""; }; + D512A46B27AAFCA400057524 /* Audio.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Audio.swift; sourceTree = ""; }; + D512A46D27AAFCAB00057524 /* Camera.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Camera.swift; sourceTree = ""; }; + D512A47627AB1FAA00057524 /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = ""; }; + D512A47827AB1FE500057524 /* AudioRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorder.swift; sourceTree = ""; }; + D512A47A27AB202400057524 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; + D512A47C27AB205400057524 /* Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helper.swift; sourceTree = ""; }; + D512A47E27AB207D00057524 /* RecordingDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordingDataModel.swift; sourceTree = ""; }; + D512A48027AB20CB00057524 /* RecordingsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordingsList.swift; sourceTree = ""; }; + D512A48227AC66FC00057524 /* Journal-it-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Journal-it-Info.plist"; sourceTree = SOURCE_ROOT; }; + D5B24D8D27A9CB61006CCCF9 /* Journal.it.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Journal.it.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D5B24D9027A9CB61006CCCF9 /* Journal_itApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Journal_itApp.swift; sourceTree = ""; }; + D5B24D9227A9CB61006CCCF9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + D5B24D9427A9CB64006CCCF9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D5B24D9727A9CB64006CCCF9 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D5B24D8A27A9CB61006CCCF9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D512A47127AAFD3A00057524 /* HighlightedTextEditor in Frameworks */, + D512A47427AB076A00057524 /* SwiftUIKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D512A47527AB1D9700057524 /* Audio */ = { + isa = PBXGroup; + children = ( + D512A47627AB1FAA00057524 /* AudioPlayer.swift */, + D512A47827AB1FE500057524 /* AudioRecorder.swift */, + D512A47A27AB202400057524 /* Extensions.swift */, + D512A47C27AB205400057524 /* Helper.swift */, + D512A47E27AB207D00057524 /* RecordingDataModel.swift */, + D512A48027AB20CB00057524 /* RecordingsList.swift */, + ); + path = Audio; + sourceTree = ""; + }; + D5B24D8427A9CB61006CCCF9 = { + isa = PBXGroup; + children = ( + D5B24D8F27A9CB61006CCCF9 /* Journal.it */, + D5B24D8E27A9CB61006CCCF9 /* Products */, + ); + sourceTree = ""; + }; + D5B24D8E27A9CB61006CCCF9 /* Products */ = { + isa = PBXGroup; + children = ( + D5B24D8D27A9CB61006CCCF9 /* Journal.it.app */, + ); + name = Products; + sourceTree = ""; + }; + D5B24D8F27A9CB61006CCCF9 /* Journal.it */ = { + isa = PBXGroup; + children = ( + D512A48227AC66FC00057524 /* Journal-it-Info.plist */, + D512A47527AB1D9700057524 /* Audio */, + D5B24D9027A9CB61006CCCF9 /* Journal_itApp.swift */, + D5B24D9227A9CB61006CCCF9 /* ContentView.swift */, + D5B24D9427A9CB64006CCCF9 /* Assets.xcassets */, + D5B24D9627A9CB64006CCCF9 /* Preview Content */, + D512A46727AAFB5D00057524 /* SettingsView.swift */, + D512A46927AAFC9C00057524 /* Notes.swift */, + D512A46B27AAFCA400057524 /* Audio.swift */, + D512A46D27AAFCAB00057524 /* Camera.swift */, + ); + path = Journal.it; + sourceTree = ""; + }; + D5B24D9627A9CB64006CCCF9 /* Preview Content */ = { + isa = PBXGroup; + children = ( + D5B24D9727A9CB64006CCCF9 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + D5B24D8C27A9CB61006CCCF9 /* Journal.it */ = { + isa = PBXNativeTarget; + buildConfigurationList = D5B24D9B27A9CB64006CCCF9 /* Build configuration list for PBXNativeTarget "Journal.it" */; + buildPhases = ( + D5B24D8927A9CB61006CCCF9 /* Sources */, + D5B24D8A27A9CB61006CCCF9 /* Frameworks */, + D5B24D8B27A9CB61006CCCF9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Journal.it; + packageProductDependencies = ( + D512A47027AAFD3A00057524 /* HighlightedTextEditor */, + D512A47327AB076A00057524 /* SwiftUIKit */, + ); + productName = Journal.it; + productReference = D5B24D8D27A9CB61006CCCF9 /* Journal.it.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D5B24D8527A9CB61006CCCF9 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1310; + LastUpgradeCheck = 1310; + TargetAttributes = { + D5B24D8C27A9CB61006CCCF9 = { + CreatedOnToolsVersion = 13.1; + }; + }; + }; + buildConfigurationList = D5B24D8827A9CB61006CCCF9 /* Build configuration list for PBXProject "Journal.it" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = D5B24D8427A9CB61006CCCF9; + packageReferences = ( + D512A46F27AAFD3A00057524 /* XCRemoteSwiftPackageReference "HighlightedTextEditor" */, + D512A47227AB076900057524 /* XCRemoteSwiftPackageReference "SwiftUIKit" */, + ); + productRefGroup = D5B24D8E27A9CB61006CCCF9 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D5B24D8C27A9CB61006CCCF9 /* Journal.it */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D5B24D8B27A9CB61006CCCF9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5B24D9827A9CB64006CCCF9 /* Preview Assets.xcassets in Resources */, + D5B24D9527A9CB64006CCCF9 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D5B24D8927A9CB61006CCCF9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D512A46827AAFB5D00057524 /* SettingsView.swift in Sources */, + D512A47F27AB207D00057524 /* RecordingDataModel.swift in Sources */, + D512A47B27AB202400057524 /* Extensions.swift in Sources */, + D512A48127AB20CB00057524 /* RecordingsList.swift in Sources */, + D5B24D9327A9CB61006CCCF9 /* ContentView.swift in Sources */, + D512A46E27AAFCAB00057524 /* Camera.swift in Sources */, + D5B24D9127A9CB61006CCCF9 /* Journal_itApp.swift in Sources */, + D512A46A27AAFC9C00057524 /* Notes.swift in Sources */, + D512A46C27AAFCA400057524 /* Audio.swift in Sources */, + D512A47D27AB205400057524 /* Helper.swift in Sources */, + D512A47927AB1FE500057524 /* AudioRecorder.swift in Sources */, + D512A47727AB1FAA00057524 /* AudioPlayer.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + D5B24D9927A9CB64006CCCF9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + D5B24D9A27A9CB64006CCCF9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D5B24D9C27A9CB64006CCCF9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Journal.it/Preview Content\""; + DEVELOPMENT_TEAM = ZWASU9HFBU; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Journal-it-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = Journal.it; + INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES; + INFOPLIST_KEY_NSCameraUsageDescription = "To Take Pictures, You Must Allow Access To The Camera."; + INFOPLIST_KEY_NSMicrophoneUsageDescription = "To Record Audio, You Must Allow Access To The Microphone."; + INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "To Save Photos To The Photo Library, You Must Allow Access."; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.MSJ.Journal-it"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + D5B24D9D27A9CB64006CCCF9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Journal.it/Preview Content\""; + DEVELOPMENT_TEAM = ZWASU9HFBU; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Journal-it-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = Journal.it; + INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES; + INFOPLIST_KEY_NSCameraUsageDescription = "To Take Pictures, You Must Allow Access To The Camera."; + INFOPLIST_KEY_NSMicrophoneUsageDescription = "To Record Audio, You Must Allow Access To The Microphone."; + INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "To Save Photos To The Photo Library, You Must Allow Access."; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.MSJ.Journal-it"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D5B24D8827A9CB61006CCCF9 /* Build configuration list for PBXProject "Journal.it" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D5B24D9927A9CB64006CCCF9 /* Debug */, + D5B24D9A27A9CB64006CCCF9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D5B24D9B27A9CB64006CCCF9 /* Build configuration list for PBXNativeTarget "Journal.it" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D5B24D9C27A9CB64006CCCF9 /* Debug */, + D5B24D9D27A9CB64006CCCF9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + D512A46F27AAFD3A00057524 /* XCRemoteSwiftPackageReference "HighlightedTextEditor" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/kyle-n/HighlightedTextEditor"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.0.0; + }; + }; + D512A47227AB076900057524 /* XCRemoteSwiftPackageReference "SwiftUIKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/danielsaidi/SwiftUIKit"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.0.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + D512A47027AAFD3A00057524 /* HighlightedTextEditor */ = { + isa = XCSwiftPackageProductDependency; + package = D512A46F27AAFD3A00057524 /* XCRemoteSwiftPackageReference "HighlightedTextEditor" */; + productName = HighlightedTextEditor; + }; + D512A47327AB076A00057524 /* SwiftUIKit */ = { + isa = XCSwiftPackageProductDependency; + package = D512A47227AB076900057524 /* XCRemoteSwiftPackageReference "SwiftUIKit" */; + productName = SwiftUIKit; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = D5B24D8527A9CB61006CCCF9 /* Project object */; +} diff --git a/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..3f0055c --- /dev/null +++ b/Source Code/Journal.it/Journal.it.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,25 @@ +{ + "object": { + "pins": [ + { + "package": "HighlightedTextEditor", + "repositoryURL": "https://github.com/kyle-n/HighlightedTextEditor", + "state": { + "branch": null, + "revision": "7069ede002afc6bde867aef7035f45ff72dc839c", + "version": "2.1.0" + } + }, + { + "package": "SwiftUIKit", + "repositoryURL": "https://github.com/danielsaidi/SwiftUIKit", + "state": { + "branch": null, + "revision": "9bfab2d0913e372015f32eff86850d3a76e7c41d", + "version": "2.3.3" + } + } + ] + }, + "version": 1 +} diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AccentColor.colorset/Contents.json b/Source Code/Journal.it/Journal.it/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..e66a540 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,15 @@ +{ + "colors" : [ + { + "color" : { + "platform" : "universal", + "reference" : "systemGreenColor" + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/1024.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000..cf9737b Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/120-1.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/120-1.png new file mode 100644 index 0000000..4a63c8d Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/120-1.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/120.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000..4a63c8d Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/152.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000..b26c4e1 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/167.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000..f4c0f3c Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/180.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 0000000..b0db07e Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/20.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/20.png new file mode 100644 index 0000000..715030c Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/29.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000..e39bd9b Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40-1.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40-1.png new file mode 100644 index 0000000..e2b4198 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40-1.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40-2.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40-2.png new file mode 100644 index 0000000..e2b4198 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40-2.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000..e2b4198 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/58-1.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/58-1.png new file mode 100644 index 0000000..6477ab9 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/58-1.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/58.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000..6477ab9 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/60.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000..1237484 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/76.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/76.png new file mode 100644 index 0000000..e5ea90b Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/80-1.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/80-1.png new file mode 100644 index 0000000..a3d0a4a Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/80-1.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/80.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 0000000..a3d0a4a Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/87.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000..d957133 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/87.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/Contents.json b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..e594077 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "filename" : "40.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "60.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "58.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "87.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "80.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "120.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "120-1.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "180.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "20.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "40-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "29.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "58-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "40-2.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "80-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "76.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "152.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "167.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "1024.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppsIcon.imageset/Contents.json b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppsIcon.imageset/Contents.json new file mode 100644 index 0000000..a2ad99b --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppsIcon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Journal.it iOS App Icon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/AppsIcon.imageset/Journal.it iOS App Icon.png b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppsIcon.imageset/Journal.it iOS App Icon.png new file mode 100644 index 0000000..3fe6f03 Binary files /dev/null and b/Source Code/Journal.it/Journal.it/Assets.xcassets/AppsIcon.imageset/Journal.it iOS App Icon.png differ diff --git a/Source Code/Journal.it/Journal.it/Assets.xcassets/Contents.json b/Source Code/Journal.it/Journal.it/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Source Code/Journal.it/Journal.it/Audio.swift b/Source Code/Journal.it/Journal.it/Audio.swift new file mode 100644 index 0000000..70fd0da --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Audio.swift @@ -0,0 +1,159 @@ +// +// Audio.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import SwiftUI + +struct Audio: View { + @Environment(\.horizontalSizeClass) var horizontalSizeClass + @Environment(\.colorScheme) var colorScheme + @ObservedObject var audioRecorder: AudioRecorder + var body: some View { + if horizontalSizeClass == .compact { + NavigationView { + VStack { + RecordingsList(audioRecorder: audioRecorder) + if audioRecorder.recording == false { + Button(action: {self.audioRecorder.startRecording()}) { + ZStack { + if colorScheme == .dark { + Image(systemName: "circle.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 80, height: 80) + .clipped() + .foregroundColor(.white) + .padding(.bottom, 40) + } else { + Image(systemName: "circle.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 80, height: 80) + .clipped() + .foregroundColor(.black) + .padding(.bottom, 40) + } + Image(systemName: "circle.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 70, height: 70) + .clipped() + .foregroundColor(.red) + .padding(.bottom, 40) + } + } + } else { + Button(action: {self.audioRecorder.stopRecording()}) { + ZStack { + if colorScheme == .dark { + Image(systemName: "stop.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 80, height: 80) + .clipped() + .foregroundColor(.white) + .padding(.bottom, 40) + } else { + Image(systemName: "stop.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 80, height: 80) + .clipped() + .foregroundColor(.black) + .padding(.bottom, 40) + } + Image(systemName: "stop.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 70, height: 70) + .clipped() + .foregroundColor(.red) + .padding(.bottom, 40) + } + } + } + } + .navigationTitle("Audio") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + EditButton() + } + } + } + } else { + VStack { + RecordingsList(audioRecorder: audioRecorder) + if audioRecorder.recording == false { + Button(action: {self.audioRecorder.startRecording()}) { + ZStack { + if colorScheme == .dark { + Image(systemName: "circle.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 80, height: 80) + .clipped() + .foregroundColor(.white) + .padding(.bottom, 40) + } else { + Image(systemName: "circle.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 80, height: 80) + .clipped() + .foregroundColor(.black) + .padding(.bottom, 40) + } + Image(systemName: "circle.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 70, height: 70) + .clipped() + .foregroundColor(.red) + .padding(.bottom, 40) + } + } + } else { + Button(action: {self.audioRecorder.stopRecording()}) { + ZStack { + if colorScheme == .dark { + Image(systemName: "stop.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 80, height: 80) + .clipped() + .foregroundColor(.white) + .padding(.bottom, 40) + } else { + Image(systemName: "stop.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 80, height: 80) + .clipped() + .foregroundColor(.black) + .padding(.bottom, 40) + } + Image(systemName: "stop.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 70, height: 70) + .clipped() + .foregroundColor(.red) + .padding(.bottom, 40) + } + } + } + } + .navigationTitle("Audio") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + EditButton() + } + } + } + } +} diff --git a/Source Code/Journal.it/Journal.it/Audio/AudioPlayer.swift b/Source Code/Journal.it/Journal.it/Audio/AudioPlayer.swift new file mode 100644 index 0000000..4621312 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Audio/AudioPlayer.swift @@ -0,0 +1,55 @@ +// +// AudioPlayer.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import Foundation +import SwiftUI +import Combine +import AVFoundation + +class AudioPlayer: NSObject, ObservableObject, AVAudioPlayerDelegate { + + let objectWillChange = PassthroughSubject() + + var isPlaying = false { + didSet { + objectWillChange.send(self) + } + } + + var audioPlayer: AVAudioPlayer! + + func startPlayback(audio: URL) { + let playbackSession = AVAudioSession.sharedInstance() + + do { + try playbackSession.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker) + } catch { + print("Playing Over Speakers Failed") + } + + do { + audioPlayer = try AVAudioPlayer(contentsOf: audio) + audioPlayer.delegate = self + audioPlayer.play() + isPlaying = true + } catch { + print("Playback Failed") + } + } + + func stopPlayback() { + audioPlayer.stop() + isPlaying = false + } + + func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { + if flag { + isPlaying = false + } + } +} + diff --git a/Source Code/Journal.it/Journal.it/Audio/AudioRecorder.swift b/Source Code/Journal.it/Journal.it/Audio/AudioRecorder.swift new file mode 100644 index 0000000..bf5abac --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Audio/AudioRecorder.swift @@ -0,0 +1,98 @@ +// +// AudioRecorder.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import Foundation +import SwiftUI +import Combine +import AVFoundation + +class AudioRecorder: NSObject, ObservableObject { + + override init() { + super.init() + fetchRecording() + } + + let objectWillChange = PassthroughSubject() + + var audioRecorder: AVAudioRecorder! + + var recordings = [Recording]() + + var recording = false { + didSet { + objectWillChange.send(self) + } + } + + func startRecording() { + let recordingSession = AVAudioSession.sharedInstance() + + do { + try recordingSession.setCategory(.playAndRecord, mode: .default) + try recordingSession.setActive(true) + } catch { + print("Failed To Set Up Recording Session") + } + + let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + let audioFilename = documentPath.appendingPathComponent("\(Date().toString(dateFormat: "dd-MM-YY 'At' HH:mm:ss")).m4a") + + let settings = [ + AVFormatIDKey: Int(kAudioFormatMPEG4AAC), + AVSampleRateKey: 12000, + AVNumberOfChannelsKey: 1, + AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue + ] + + do { + audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings) + audioRecorder.record() + + recording = true + } catch { + print("Could Not Start Recording") + } + } + + func stopRecording() { + audioRecorder.stop() + recording = false + + fetchRecording() + } + + func fetchRecording() { + recordings.removeAll() + + let fileManager = FileManager.default + let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0] + let directoryContents = try! fileManager.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: nil) + for audio in directoryContents { + let recording = Recording(fileURL: audio, createdAt: getFileDate(for: audio)) + recordings.append(recording) + } + + recordings.sort(by: { $0.createdAt.compare($1.createdAt) == .orderedAscending}) + + objectWillChange.send(self) + } + + func deleteRecording(urlsToDelete: [URL]) { + + for url in urlsToDelete { + print(url) + do { + try FileManager.default.removeItem(at: url) + } catch { + print("File Could Not Be Deleted") + } + } + + fetchRecording() + } +} diff --git a/Source Code/Journal.it/Journal.it/Audio/Extensions.swift b/Source Code/Journal.it/Journal.it/Audio/Extensions.swift new file mode 100644 index 0000000..06b8e03 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Audio/Extensions.swift @@ -0,0 +1,16 @@ +// +// Extensions.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import Foundation + +extension Date { + func toString(dateFormat format: String ) -> String { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = format + return dateFormatter.string(from: self) + } +} diff --git a/Source Code/Journal.it/Journal.it/Audio/Helper.swift b/Source Code/Journal.it/Journal.it/Audio/Helper.swift new file mode 100644 index 0000000..7227862 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Audio/Helper.swift @@ -0,0 +1,17 @@ +// +// Helper.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import Foundation + +func getFileDate(for file: URL) -> Date { + if let attributes = try? FileManager.default.attributesOfItem(atPath: file.path) as [FileAttributeKey: Any], + let creationDate = attributes[FileAttributeKey.creationDate] as? Date { + return creationDate + } else { + return Date() + } +} diff --git a/Source Code/Journal.it/Journal.it/Audio/RecordingDataModel.swift b/Source Code/Journal.it/Journal.it/Audio/RecordingDataModel.swift new file mode 100644 index 0000000..07e5c6c --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Audio/RecordingDataModel.swift @@ -0,0 +1,13 @@ +// +// RecordingDataModel.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import Foundation + +struct Recording { + let fileURL: URL + let createdAt: Date +} diff --git a/Source Code/Journal.it/Journal.it/Audio/RecordingsList.swift b/Source Code/Journal.it/Journal.it/Audio/RecordingsList.swift new file mode 100644 index 0000000..ecd5375 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Audio/RecordingsList.swift @@ -0,0 +1,63 @@ +// +// RecordingsList.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import SwiftUI + +struct RecordingsList: View { + @ObservedObject var audioRecorder: AudioRecorder + @State var showingShareSheet = false + var body: some View { + List { + ForEach(audioRecorder.recordings, id: \.createdAt) { recording in + RecordingRow(audioURL: recording.fileURL) + } + .onDelete(perform: delete) + } + } + + func delete(at offsets: IndexSet) { + var urlsToDelete = [URL]() + for index in offsets { + urlsToDelete.append(audioRecorder.recordings[index].fileURL) + } + audioRecorder.deleteRecording(urlsToDelete: urlsToDelete) + } +} + +struct RecordingRow: View { + var audioURL: URL + @ObservedObject var audioPlayer = AudioPlayer() + var body: some View { + HStack { + Text("\(audioURL.lastPathComponent)") + Spacer() + if audioPlayer.isPlaying == false { + Button(action: { + self.audioPlayer.startPlayback(audio: self.audioURL) + }) { + Image(systemName: "play.fill") + .imageScale(.large) + .foregroundColor(.accentColor) + } + } else { + Button(action: { + self.audioPlayer.stopPlayback() + }) { + Image(systemName: "stop.fill") + .imageScale(.large) + .foregroundColor(.accentColor) + } + } + } + } +} + +struct RecordingsList_Previews: PreviewProvider { + static var previews: some View { + RecordingsList(audioRecorder: AudioRecorder()) + } +} diff --git a/Source Code/Journal.it/Journal.it/Camera.swift b/Source Code/Journal.it/Journal.it/Camera.swift new file mode 100644 index 0000000..fba7049 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Camera.swift @@ -0,0 +1,102 @@ +// +// Camera.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import SwiftUI +import SwiftUIKit + +struct Camera: View { + @Environment(\.horizontalSizeClass) var horizontalSizeClass + @State private var photos = [Image]() + @StateObject private var sheetContext = FullScreenCoverContext() + var body: some View { + if horizontalSizeClass == .compact { + NavigationView { + Button(action: {openCamera()}) { + Label("Open Camera", systemImage: "camera.fill") + } + .buttonStyle(.bordered) + .tint(.accentColor) + .navigationTitle("Camera") + .navigationBarTitleDisplayMode(.inline) + } + .fullScreenCover(context: sheetContext) + } else { + Button(action: {openCamera()}) { + Label("Open Camera", systemImage: "camera.fill") + } + .buttonStyle(.bordered) + .tint(.accentColor) + .navigationTitle("Camera") + .navigationBarTitleDisplayMode(.inline) + .fullScreenCover(context: sheetContext) + } + } +} + +struct Camera_Previews: PreviewProvider { + static var previews: some View { + Camera() + } +} + +extension Camera { + + func createCamera() -> some View { + PhotoCamera( + cancelAction: dismissCamera, + resultAction: handleResult) + .edgesIgnoringSafeArea(.all) + } + + func dismissCamera() { + sheetContext.dismiss() + } + + func handleResult(_ result: PhotoCamera.CameraResult) { + switch result { + case .failure: dismissCamera() + case .success(let photo): savePhoto(photo) + } + } + + func openCamera() { + sheetContext.present(createCamera()) + } + + func savePhoto(_ photo: ImageResource) { + let image: Image = Image(imageResource: photo) + let uiImage: UIImage = image.asUIImage() + UIImageWriteToSavedPhotosAlbum(uiImage, nil, nil, nil) + dismissCamera() + } +} + +extension View { + public func asUIImage() -> UIImage { + let controller = UIHostingController(rootView: self) + + controller.view.frame = CGRect(x: 0, y: CGFloat(Int.max), width: 1, height: 1) + UIApplication.shared.windows.first!.rootViewController?.view.addSubview(controller.view) + + let size = controller.sizeThatFits(in: UIScreen.main.bounds.size) + controller.view.bounds = CGRect(origin: .zero, size: size) + controller.view.sizeToFit() + + let image = controller.view.asUIImage() + controller.view.removeFromSuperview() + return image + } +} + +extension UIView { + public func asUIImage() -> UIImage { + let renderer = UIGraphicsImageRenderer(bounds: bounds) + return renderer.image { rendererContext in + layer.render(in: rendererContext.cgContext) + } + } +} diff --git a/Source Code/Journal.it/Journal.it/ContentView.swift b/Source Code/Journal.it/Journal.it/ContentView.swift new file mode 100644 index 0000000..c2226c9 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/ContentView.swift @@ -0,0 +1,115 @@ +// +// ContentView.swift +// Journal.it +// +// Created by Mark Howard on 01/02/2022. +// + +import SwiftUI + +struct ContentView: View { + @Environment(\.horizontalSizeClass) var horizontalSizeClass + @State var tabSelection = 1 + @ObservedObject var audioRecorder: AudioRecorder + @State var showingSettings = false + var body: some View { + if horizontalSizeClass == .compact { + TabView(selection: $tabSelection) { + Notes() + .tag(1) + .tabItem { + VStack { + Image(systemName: "note.text") + Text("Notes") + } + } + Audio(audioRecorder: audioRecorder) + .tag(2) + .tabItem { + VStack { + Image(systemName: "mic") + Text("Audio") + } + } + Camera() + .tag(3) + .tabItem { + VStack { + Image(systemName: "camera") + Text("Camera") + } + } + NavigationView { + SettingsView() + .navigationTitle("Settings") + } + .tag(4) + .tabItem { + VStack { + Image(systemName: "gearshape") + Text("Settings") + } + } + } + } else { + NavigationView { + List { + NavigationLink(destination: Notes()) { + Label("Notes", systemImage: "note.text") + } + NavigationLink(destination: Audio(audioRecorder: audioRecorder)) { + Label("Audio", systemImage: "mic") + } + NavigationLink(destination: Camera()) { + Label("Camera", systemImage: "camera") + } + } + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button(action: {self.showingSettings = true}) { + Image(systemName: "gearshape") + } + .sheet(isPresented: $showingSettings) { + NavigationView { + SettingsView() + .navigationTitle("Settings") + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button(action: {self.showingSettings = false}) { + Text("Done") + } + } + } + } + } + } + } + .listStyle(SidebarListStyle()) + .navigationTitle("Journal.it") + VStack { + Image("AppsIcon") + .resizable() + .cornerRadius(25) + .frame(width: 150, height: 150) + Text("Journal.it") + .font(.title2) + .bold() + .padding() + } + } + } + } +} + + +struct ActivityView: UIViewControllerRepresentable { + let activityItems: [Any] + let applicationActivities: [UIActivity]? + + func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIActivityViewController { + return UIActivityViewController(activityItems: activityItems, applicationActivities: applicationActivities) + } + func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { + + } +} diff --git a/Source Code/Journal.it/Journal.it/Journal_itApp.swift b/Source Code/Journal.it/Journal.it/Journal_itApp.swift new file mode 100644 index 0000000..39685c3 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Journal_itApp.swift @@ -0,0 +1,17 @@ +// +// Journal_itApp.swift +// Journal.it +// +// Created by Mark Howard on 01/02/2022. +// + +import SwiftUI + +@main +struct Journal_itApp: App { + var body: some Scene { + WindowGroup { + ContentView(audioRecorder: AudioRecorder()) + } + } +} diff --git a/Source Code/Journal.it/Journal.it/Notes.swift b/Source Code/Journal.it/Journal.it/Notes.swift new file mode 100644 index 0000000..f7ad4a5 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Notes.swift @@ -0,0 +1,100 @@ +// +// Notes.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import SwiftUI +import HighlightedTextEditor + +struct Notes: View { + @Environment(\.horizontalSizeClass) var horizontalSizeClass + @State var showingShareSheet = false + @AppStorage("notes") var notes: String = "Type Some Notes Here..." + var body: some View { + if horizontalSizeClass == .compact { + NavigationView { + VStack { + HighlightedTextEditor(text: $notes, highlightRules: .url) + .onCommit { + print("Commited") + } + .onEditingChanged { + print("Editing Changed") + } + .onTextChange { + print("Lastest Text Value", $0) + } + .onSelectionChange { + (range: NSRange) in + print(range) + } + .introspect { editor in + editor.textView.backgroundColor = .clear + } + } + .navigationTitle("Notes") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(action: {UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)}) { + Image(systemName: "keyboard.chevron.compact.down") + } + } + ToolbarItem(placement: .navigationBarTrailing) { + Button(action: {self.showingShareSheet = true}) { + Image(systemName: "square.and.arrow.up") + } + .sheet(isPresented: $showingShareSheet) { + ActivityView(activityItems: [notes] as [Any], applicationActivities: nil) + } + } + } + } + } else { + VStack { + HighlightedTextEditor(text: $notes, highlightRules: .url) + .onCommit { + print("Commited") + } + .onEditingChanged { + print("Editing Changed") + } + .onTextChange { + print("Lastest Text Value", $0) + } + .onSelectionChange { + (range: NSRange) in + print(range) + } + .introspect { editor in + editor.textView.backgroundColor = .clear + } + } + .navigationTitle("Notes") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(action: {UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)}) { + Image(systemName: "keyboard.chevron.compact.down") + } + } + ToolbarItem(placement: .navigationBarTrailing) { + Button(action: {self.showingShareSheet = true}) { + Image(systemName: "square.and.arrow.up") + } + .sheet(isPresented: $showingShareSheet) { + ActivityView(activityItems: [notes] as [Any], applicationActivities: nil) + } + } + } + } + } +} + +struct Notes_Previews: PreviewProvider { + static var previews: some View { + Notes() + } +} diff --git a/Source Code/Journal.it/Journal.it/Preview Content/Preview Assets.xcassets/Contents.json b/Source Code/Journal.it/Journal.it/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Source Code/Journal.it/Journal.it/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Source Code/Journal.it/Journal.it/SettingsView.swift b/Source Code/Journal.it/Journal.it/SettingsView.swift new file mode 100644 index 0000000..7ae127e --- /dev/null +++ b/Source Code/Journal.it/Journal.it/SettingsView.swift @@ -0,0 +1,31 @@ +// +// SettingsView.swift +// Journal.it +// +// Created by Mark Howard on 02/02/2022. +// + +import SwiftUI + +struct SettingsView: View { + var body: some View { + Form { + HStack { + Text("Version") + Spacer() + Text("1.0") + } + HStack { + Text("Build") + Spacer() + Text("1") + } + } + } +} + +struct SettingsView_Previews: PreviewProvider { + static var previews: some View { + SettingsView() + } +}