Skip to content

Commit

Permalink
feat: adding a review manager
Browse files Browse the repository at this point in the history
  • Loading branch information
wkaisertexas committed Mar 20, 2024
1 parent b218ddf commit 58ec029
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 7 deletions.
39 changes: 39 additions & 0 deletions TimeLapze.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@
objects = {

/* Begin PBXBuildFile section */
3E0DCD742BAB2A5800DB969A /* ReviewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E0DCD732BAB2A5800DB969A /* ReviewManager.swift */; };
3E23A01E2B2FC65A0016DE8C /* TimeLapzeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E23A01D2B2FC65A0016DE8C /* TimeLapzeTests.swift */; };
3E4D87C729AD741800D3EC7B /* Screen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E4D87C629AD741800D3EC7B /* Screen.swift */; };
3E4D87C929AD744C00D3EC7B /* Camera.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E4D87C829AD744C00D3EC7B /* Camera.swift */; };
3E5130E02BA34FE500A628EB /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E5130DF2BA34FE500A628EB /* OnboardingView.swift */; };
3E61935B2A2EC12200333918 /* VideoConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E61935A2A2EC12200333918 /* VideoConfiguration.swift */; };
3E75E34C2AED6EC90016EB52 /* CameraRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E75E34B2AED6EC90016EB52 /* CameraRecorder.swift */; };
3E75E34E2AF17A870016EB52 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 3E75E34D2AF17A870016EB52 /* LICENSE */; };
3E75E3502AF2005A0016EB52 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E75E34F2AF2005A0016EB52 /* PreferencesView.swift */; };
3E87A932299EBDFF00714AFC /* RecorderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E87A931299EBDFF00714AFC /* RecorderViewModel.swift */; };
3E87A934299EBE0D00714AFC /* Recordable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E87A933299EBE0D00714AFC /* Recordable.swift */; };
3E9894D12A2ED44600C25059 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E9894D02A2ED44600C25059 /* Logger.swift */; };
3EAB1AFB2BA89E6800BEC597 /* SettingsAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 3EAB1AFA2BA89E6800BEC597 /* SettingsAccess */; };
3EAB1AFD2BA8A33300BEC597 /* OnboardingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EAB1AFC2BA8A33300BEC597 /* OnboardingViewModel.swift */; };
3EE5FE0D296232C700768BF7 /* TimeLapzeApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EE5FE0C296232C700768BF7 /* TimeLapzeApp.swift */; };
3EE5FE0F296232C700768BF7 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EE5FE0E296232C700768BF7 /* ContentView.swift */; };
3EE5FE11296232C800768BF7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3EE5FE10296232C800768BF7 /* Assets.xcassets */; };
Expand All @@ -35,11 +39,13 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
3E0DCD732BAB2A5800DB969A /* ReviewManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewManager.swift; sourceTree = "<group>"; };
3E23A01B2B2FC65A0016DE8C /* TimeLapzeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TimeLapzeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3E23A01D2B2FC65A0016DE8C /* TimeLapzeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeLapzeTests.swift; sourceTree = "<group>"; };
3E2EB6A429AD5A4C006F4F2A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
3E4D87C629AD741800D3EC7B /* Screen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Screen.swift; sourceTree = "<group>"; };
3E4D87C829AD744C00D3EC7B /* Camera.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Camera.swift; sourceTree = "<group>"; };
3E5130DF2BA34FE500A628EB /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = "<group>"; };
3E571FDF29AF248500AD153D /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
3E61935A2A2EC12200333918 /* VideoConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoConfiguration.swift; sourceTree = "<group>"; };
3E75E34B2AED6EC90016EB52 /* CameraRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraRecorder.swift; sourceTree = "<group>"; };
Expand All @@ -48,6 +54,7 @@
3E87A931299EBDFF00714AFC /* RecorderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecorderViewModel.swift; sourceTree = "<group>"; };
3E87A933299EBE0D00714AFC /* Recordable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Recordable.swift; sourceTree = "<group>"; };
3E9894D02A2ED44600C25059 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
3EAB1AFC2BA8A33300BEC597 /* OnboardingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewModel.swift; sourceTree = "<group>"; };
3EE5FE09296232C700768BF7 /* TimeLapze.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TimeLapze.app; sourceTree = BUILT_PRODUCTS_DIR; };
3EE5FE0C296232C700768BF7 /* TimeLapzeApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeLapzeApp.swift; sourceTree = "<group>"; };
3EE5FE0E296232C700768BF7 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand All @@ -69,6 +76,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3EAB1AFB2BA89E6800BEC597 /* SettingsAccess in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -129,6 +137,9 @@
3E9894D02A2ED44600C25059 /* Logger.swift */,
3E75E34B2AED6EC90016EB52 /* CameraRecorder.swift */,
3E75E34F2AF2005A0016EB52 /* PreferencesView.swift */,
3E5130DF2BA34FE500A628EB /* OnboardingView.swift */,
3EAB1AFC2BA8A33300BEC597 /* OnboardingViewModel.swift */,
3E0DCD732BAB2A5800DB969A /* ReviewManager.swift */,
);
path = TimeLapze;
sourceTree = "<group>";
Expand Down Expand Up @@ -175,6 +186,9 @@
dependencies = (
);
name = TimeLapze;
packageProductDependencies = (
3EAB1AFA2BA89E6800BEC597 /* SettingsAccess */,
);
productName = ScreenTimeLapse;
productReference = 3EE5FE09296232C700768BF7 /* TimeLapze.app */;
productType = "com.apple.product-type.application";
Expand Down Expand Up @@ -207,6 +221,9 @@
Base,
);
mainGroup = 3EE5FE00296232C700768BF7;
packageReferences = (
3EAB1AF92BA89E6800BEC597 /* XCRemoteSwiftPackageReference "SettingsAccess" */,
);
productRefGroup = 3EE5FE0A296232C700768BF7 /* Products */;
projectDirPath = "";
projectRoot = "";
Expand Down Expand Up @@ -253,12 +270,15 @@
3E61935B2A2EC12200333918 /* VideoConfiguration.swift in Sources */,
3E75E3502AF2005A0016EB52 /* PreferencesView.swift in Sources */,
3E87A932299EBDFF00714AFC /* RecorderViewModel.swift in Sources */,
3E0DCD742BAB2A5800DB969A /* ReviewManager.swift in Sources */,
3E75E34C2AED6EC90016EB52 /* CameraRecorder.swift in Sources */,
3EEFFBB929A9B662002D0040 /* Utils.swift in Sources */,
3E87A934299EBE0D00714AFC /* Recordable.swift in Sources */,
3EAB1AFD2BA8A33300BEC597 /* OnboardingViewModel.swift in Sources */,
3E9894D12A2ED44600C25059 /* Logger.swift in Sources */,
3EE5FE0F296232C700768BF7 /* ContentView.swift in Sources */,
3EE5FE0D296232C700768BF7 /* TimeLapzeApp.swift in Sources */,
3E5130E02BA34FE500A628EB /* OnboardingView.swift in Sources */,
3E4D87C729AD741800D3EC7B /* Screen.swift in Sources */,
3E4D87C929AD744C00D3EC7B /* Camera.swift in Sources */,
);
Expand Down Expand Up @@ -546,6 +566,25 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
3EAB1AF92BA89E6800BEC597 /* XCRemoteSwiftPackageReference "SettingsAccess" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/orchetect/SettingsAccess";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.4.0;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
3EAB1AFA2BA89E6800BEC597 /* SettingsAccess */ = {
isa = XCSwiftPackageProductDependency;
package = 3EAB1AF92BA89E6800BEC597 /* XCRemoteSwiftPackageReference "SettingsAccess" */;
productName = SettingsAccess;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 3EE5FE01296232C700768BF7 /* Project object */;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions TimeLapze/RecorderViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class RecorderViewModel: ObservableObject {
apps.keys.filter { !apps[$0]! }.sorted(by: <)
}

// MARK: -Recording
// MARK: Recording

/// Starts recording ``cameras`` and ``screens``
func startRecording() {
Expand Down Expand Up @@ -135,10 +135,14 @@ class RecorderViewModel: ObservableObject {
.forEach { index in
screens[index].saveRecording()
}

// Logs a recording being saved
reviewManager.logCompletedRecordings()
}

// MARK: -Toggles

// MARK: Toggles

/// Inverts the ``Screen`` and sends an update to the user interface
func toggleScreen(screen: Screen) {
screen.enabled.toggle()
objectWillChange.send()
Expand All @@ -165,7 +169,7 @@ class RecorderViewModel: ObservableObject {
!(cameras.contains { $0.enabled } || screens.contains { $0.enabled })
}

// MARK: -Applications Menu
// MARK: Applications Menu

/// Flips the enabled and disabled app in ``apps``
func invertApplications() {
Expand Down Expand Up @@ -258,7 +262,7 @@ class RecorderViewModel: ObservableObject {
return newCameras
}

// MARK: -Timing
// MARK: Timing

/// Returns the current time (in output units) of the recording
var currentTime: CMTime {
Expand All @@ -277,7 +281,7 @@ class RecorderViewModel: ObservableObject {
return CMTime.zero
}

// MARK: -Recorder Creation
// MARK: Recorder Creation

/// Converts a `SCDisplay` into a ``Screen``
private func getScreenRecorder(_ screen: SCDisplay) -> Screen {
Expand Down
58 changes: 58 additions & 0 deletions TimeLapze/ReviewManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/// Manages review creating based on Activity Levels
import Foundation
import SwiftUI
import StoreKit

/// A logging singleton to log whenever reviews complete. Called by the ``RecorderViewModel``
struct ReviewManager {
@Environment(\.requestReview) private var requestReview

@AppStorage("lastBundleAsked") private var lastBundleAsked: String = ""
@AppStorage("timesVideoSaved") private var timesSaved = 0

private let INITIAL_REVIEW_THRESHOLD = 5 // wait for 5 videos before asking
private let FOLLOW_UP_REVIEW_THRESHOLD = 10 // wait for 10 videos before asking again

/// Logging completed recordings
func logCompletedRecordings() {
timesSaved += 1

if shouldAskForReview() {
waitAndAskForReview()
}
}

/// Determines whether or not a review should be saved
private func shouldAskForReview () -> Bool {
// Checking if we have already asked for a review
guard lastBundleAsked != Bundle.currentAppVersion else { return false }

if lastBundleAsked.count == 0 {
// Never asked before
if timesSaved < INITIAL_REVIEW_THRESHOLD { return false }
if let bundle = Bundle.currentAppVersion {
lastBundleAsked = bundle
}

return true
} else {
// Already asked once
if timesSaved < FOLLOW_UP_REVIEW_THRESHOLD { return false }
if let bundle = Bundle.currentAppVersion {
lastBundleAsked = bundle
}

return true
}
}

/// Requests a review after a certain time
private func waitAndAskForReview() {
Task {
try await Task.sleep(for: .seconds(3))
await requestReview()
}
}
}

let reviewManager = ReviewManager()

0 comments on commit 58ec029

Please sign in to comment.