jrb16 commited on
Commit
16bb415
·
1 Parent(s): b3b1190

Ask for reviews after the user has used the app a bit

Browse files
PersonalGPT.xcodeproj/project.pbxproj CHANGED
@@ -36,6 +36,9 @@
36
  48C554512A0FEE4800C96823 /* CodeBlockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C554502A0FEE4800C96823 /* CodeBlockView.swift */; };
37
  48C554532A10C66A00C96823 /* AltCodeBlockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C554522A10C66A00C96823 /* AltCodeBlockView.swift */; };
38
  48C7F7842A1CE2FD007C0A3D /* Markdown in Frameworks */ = {isa = PBXBuildFile; productRef = 48C7F7832A1CE2FD007C0A3D /* Markdown */; };
 
 
 
39
  /* End PBXBuildFile section */
40
 
41
  /* Begin PBXContainerItemProxy section */
@@ -111,6 +114,9 @@
111
  48C5544E2A0FE32B00C96823 /* ParserResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParserResult.swift; sourceTree = "<group>"; };
112
  48C554502A0FEE4800C96823 /* CodeBlockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeBlockView.swift; sourceTree = "<group>"; };
113
  48C554522A10C66A00C96823 /* AltCodeBlockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AltCodeBlockView.swift; sourceTree = "<group>"; };
 
 
 
114
  /* End PBXFileReference section */
115
 
116
  /* Begin PBXFrameworksBuildPhase section */
@@ -121,6 +127,7 @@
121
  48C7F7842A1CE2FD007C0A3D /* Markdown in Frameworks */,
122
  48241DF32A13C6A4008FB7F5 /* Accelerate.framework in Frameworks */,
123
  486279082A12463E00F45C4E /* Highlighter in Frameworks */,
 
124
  );
125
  runOnlyForDeploymentPostprocessing = 0;
126
  };
@@ -169,6 +176,7 @@
169
  48241DF12A13C6A4008FB7F5 /* Frameworks */ = {
170
  isa = PBXGroup;
171
  children = (
 
172
  48241E092A157576008FB7F5 /* Accelerate.framework */,
173
  48241DF22A13C6A4008FB7F5 /* Accelerate.framework */,
174
  );
@@ -223,6 +231,7 @@
223
  48B929A629ED80EA00607E43 /* PersonalGPT */ = {
224
  isa = PBXGroup;
225
  children = (
 
226
  4825EA802A16AFEE00A02361 /* Settings */,
227
  48B485AF2A1118A200F63766 /* Info.plist */,
228
  48B929A729ED80EA00607E43 /* PersonalGPTApp.swift */,
@@ -269,6 +278,15 @@
269
  path = PersonalGPTUITests;
270
  sourceTree = "<group>";
271
  };
 
 
 
 
 
 
 
 
 
272
  /* End PBXGroup section */
273
 
274
  /* Begin PBXNativeTarget section */
@@ -423,7 +441,9 @@
423
  48C554512A0FEE4800C96823 /* CodeBlockView.swift in Sources */,
424
  48B929AA29ED80EA00607E43 /* ContentView.swift in Sources */,
425
  48055F732A0D2B070057C3BE /* ggml.c in Sources */,
 
426
  48055F8F2A0F998F0057C3BE /* ChatBubble.swift in Sources */,
 
427
  48055F8D2A0F96E10057C3BE /* TypingIndicator.swift in Sources */,
428
  4825EA822A16B01000A02361 /* UserSettings.swift in Sources */,
429
  48B929A829ED80EA00607E43 /* PersonalGPTApp.swift in Sources */,
@@ -526,7 +546,7 @@
526
  MACOSX_DEPLOYMENT_TARGET = 13.0;
527
  MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
528
  MTL_FAST_MATH = YES;
529
- ONLY_ACTIVE_ARCH = NO;
530
  SDKROOT = macosx;
531
  SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
532
  SWIFT_OPTIMIZATION_LEVEL = "-O";
 
36
  48C554512A0FEE4800C96823 /* CodeBlockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C554502A0FEE4800C96823 /* CodeBlockView.swift */; };
37
  48C554532A10C66A00C96823 /* AltCodeBlockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C554522A10C66A00C96823 /* AltCodeBlockView.swift */; };
38
  48C7F7842A1CE2FD007C0A3D /* Markdown in Frameworks */ = {isa = PBXBuildFile; productRef = 48C7F7832A1CE2FD007C0A3D /* Markdown */; };
39
+ 48C7F7862A1CEF2D007C0A3D /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48C7F7852A1CEF2C007C0A3D /* StoreKit.framework */; };
40
+ 48C7F7882A1CEF95007C0A3D /* SKSReviewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C7F7872A1CEF95007C0A3D /* SKSReviewManager.swift */; };
41
+ 48C7F78E2A1CFDAC007C0A3D /* DeviceDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C7F78D2A1CFDAC007C0A3D /* DeviceDetection.swift */; };
42
  /* End PBXBuildFile section */
43
 
44
  /* Begin PBXContainerItemProxy section */
 
114
  48C5544E2A0FE32B00C96823 /* ParserResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParserResult.swift; sourceTree = "<group>"; };
115
  48C554502A0FEE4800C96823 /* CodeBlockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeBlockView.swift; sourceTree = "<group>"; };
116
  48C554522A10C66A00C96823 /* AltCodeBlockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AltCodeBlockView.swift; sourceTree = "<group>"; };
117
+ 48C7F7852A1CEF2C007C0A3D /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.4.sdk/System/Library/Frameworks/StoreKit.framework; sourceTree = DEVELOPER_DIR; };
118
+ 48C7F7872A1CEF95007C0A3D /* SKSReviewManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SKSReviewManager.swift; sourceTree = "<group>"; };
119
+ 48C7F78D2A1CFDAC007C0A3D /* DeviceDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceDetection.swift; sourceTree = "<group>"; };
120
  /* End PBXFileReference section */
121
 
122
  /* Begin PBXFrameworksBuildPhase section */
 
127
  48C7F7842A1CE2FD007C0A3D /* Markdown in Frameworks */,
128
  48241DF32A13C6A4008FB7F5 /* Accelerate.framework in Frameworks */,
129
  486279082A12463E00F45C4E /* Highlighter in Frameworks */,
130
+ 48C7F7862A1CEF2D007C0A3D /* StoreKit.framework in Frameworks */,
131
  );
132
  runOnlyForDeploymentPostprocessing = 0;
133
  };
 
176
  48241DF12A13C6A4008FB7F5 /* Frameworks */ = {
177
  isa = PBXGroup;
178
  children = (
179
+ 48C7F7852A1CEF2C007C0A3D /* StoreKit.framework */,
180
  48241E092A157576008FB7F5 /* Accelerate.framework */,
181
  48241DF22A13C6A4008FB7F5 /* Accelerate.framework */,
182
  );
 
231
  48B929A629ED80EA00607E43 /* PersonalGPT */ = {
232
  isa = PBXGroup;
233
  children = (
234
+ 48C7F78C2A1CFD9B007C0A3D /* Reviews */,
235
  4825EA802A16AFEE00A02361 /* Settings */,
236
  48B485AF2A1118A200F63766 /* Info.plist */,
237
  48B929A729ED80EA00607E43 /* PersonalGPTApp.swift */,
 
278
  path = PersonalGPTUITests;
279
  sourceTree = "<group>";
280
  };
281
+ 48C7F78C2A1CFD9B007C0A3D /* Reviews */ = {
282
+ isa = PBXGroup;
283
+ children = (
284
+ 48C7F7872A1CEF95007C0A3D /* SKSReviewManager.swift */,
285
+ 48C7F78D2A1CFDAC007C0A3D /* DeviceDetection.swift */,
286
+ );
287
+ path = Reviews;
288
+ sourceTree = "<group>";
289
+ };
290
  /* End PBXGroup section */
291
 
292
  /* Begin PBXNativeTarget section */
 
441
  48C554512A0FEE4800C96823 /* CodeBlockView.swift in Sources */,
442
  48B929AA29ED80EA00607E43 /* ContentView.swift in Sources */,
443
  48055F732A0D2B070057C3BE /* ggml.c in Sources */,
444
+ 48C7F78E2A1CFDAC007C0A3D /* DeviceDetection.swift in Sources */,
445
  48055F8F2A0F998F0057C3BE /* ChatBubble.swift in Sources */,
446
+ 48C7F7882A1CEF95007C0A3D /* SKSReviewManager.swift in Sources */,
447
  48055F8D2A0F96E10057C3BE /* TypingIndicator.swift in Sources */,
448
  4825EA822A16B01000A02361 /* UserSettings.swift in Sources */,
449
  48B929A829ED80EA00607E43 /* PersonalGPTApp.swift in Sources */,
 
546
  MACOSX_DEPLOYMENT_TARGET = 13.0;
547
  MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
548
  MTL_FAST_MATH = YES;
549
+ ONLY_ACTIVE_ARCH = YES;
550
  SDKROOT = macosx;
551
  SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
552
  SWIFT_OPTIMIZATION_LEVEL = "-O";
PersonalGPT.xcodeproj/xcuserdata/jeethu.xcuserdatad/xcschemes/xcschememanagement.plist CHANGED
@@ -4,6 +4,27 @@
4
  <dict>
5
  <key>SchemeUserState</key>
6
  <dict>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  <key>PersonalGPT.xcscheme_^#shared#^_</key>
8
  <dict>
9
  <key>orderHint</key>
 
4
  <dict>
5
  <key>SchemeUserState</key>
6
  <dict>
7
+ <key>DeviceKitPlayground (Playground) 1.xcscheme</key>
8
+ <dict>
9
+ <key>isShown</key>
10
+ <false/>
11
+ <key>orderHint</key>
12
+ <integer>2</integer>
13
+ </dict>
14
+ <key>DeviceKitPlayground (Playground) 2.xcscheme</key>
15
+ <dict>
16
+ <key>isShown</key>
17
+ <false/>
18
+ <key>orderHint</key>
19
+ <integer>3</integer>
20
+ </dict>
21
+ <key>DeviceKitPlayground (Playground).xcscheme</key>
22
+ <dict>
23
+ <key>isShown</key>
24
+ <false/>
25
+ <key>orderHint</key>
26
+ <integer>1</integer>
27
+ </dict>
28
  <key>PersonalGPT.xcscheme_^#shared#^_</key>
29
  <dict>
30
  <key>orderHint</key>
PersonalGPT/ChatBubble.swift CHANGED
@@ -25,7 +25,7 @@ struct ChatBubbleShape: Shape {
25
  return Path()
26
  }
27
  }
28
-
29
  private func leftBubble(in rect: CGRect) -> Path {
30
  let width = rect.width
31
  let height = rect.height
 
25
  return Path()
26
  }
27
  }
28
+
29
  private func leftBubble(in rect: CGRect) -> Path {
30
  let width = rect.width
31
  let height = rect.height
PersonalGPT/ChatState.swift CHANGED
@@ -230,6 +230,8 @@ class ChatState: ObservableObject {
230
  }
231
  }
232
  markFinish()
 
 
233
  }
234
  }
235
 
 
230
  }
231
  }
232
  markFinish()
233
+ let messageLength = backend.getMessage().count
234
+ SKSReviewManager.requestReview(generatedTextLength: messageLength)
235
  }
236
  }
237
 
PersonalGPT/PersonalGPTApp.swift CHANGED
@@ -34,7 +34,16 @@ struct PrivateAIChatApp: App {
34
  func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool {
35
  true
36
  }
 
 
 
 
37
  }
38
  #else
39
- class AppDelegate: NSObject, UIApplicationDelegate {}
 
 
 
 
 
40
  #endif
 
34
  func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool {
35
  true
36
  }
37
+
38
+ func applicationDidFinishLaunching(_: Notification) {
39
+ SKSReviewManager.incrementAppOpenCount()
40
+ }
41
  }
42
  #else
43
+ class AppDelegate: NSObject, UIApplicationDelegate {
44
+ func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
45
+ SKSReviewManager.incrementAppOpenCount()
46
+ return true
47
+ }
48
+ }
49
  #endif
PersonalGPT/Reviews/DeviceDetection.swift ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // DeviceDetection.swift
3
+ // PrivateAIChat
4
+ //
5
+ // Created by jrb16 on 23/05/2023.
6
+ //
7
+ #if os(iOS)
8
+ import UIKit
9
+
10
+ public extension UIDevice {
11
+ static let modelName: String = {
12
+ var systemInfo = utsname()
13
+ uname(&systemInfo)
14
+ let machineMirror = Mirror(reflecting: systemInfo.machine)
15
+ let identifier = machineMirror.children.reduce("") { identifier, element in
16
+ guard let value = element.value as? Int8, value != 0 else { return identifier }
17
+ return identifier + String(UnicodeScalar(UInt8(value)))
18
+ }
19
+
20
+ func mapToDevice(identifier: String) -> String { // swiftlint:disable:this cyclomatic_complexity
21
+ #if os(iOS)
22
+ switch identifier {
23
+ case "iPod5,1": return "iPod touch (5th generation)"
24
+ case "iPod7,1": return "iPod touch (6th generation)"
25
+ case "iPod9,1": return "iPod touch (7th generation)"
26
+ case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4"
27
+ case "iPhone4,1": return "iPhone 4s"
28
+ case "iPhone5,1", "iPhone5,2": return "iPhone 5"
29
+ case "iPhone5,3", "iPhone5,4": return "iPhone 5c"
30
+ case "iPhone6,1", "iPhone6,2": return "iPhone 5s"
31
+ case "iPhone7,2": return "iPhone 6"
32
+ case "iPhone7,1": return "iPhone 6 Plus"
33
+ case "iPhone8,1": return "iPhone 6s"
34
+ case "iPhone8,2": return "iPhone 6s Plus"
35
+ case "iPhone9,1", "iPhone9,3": return "iPhone 7"
36
+ case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus"
37
+ case "iPhone10,1", "iPhone10,4": return "iPhone 8"
38
+ case "iPhone10,2", "iPhone10,5": return "iPhone 8 Plus"
39
+ case "iPhone10,3", "iPhone10,6": return "iPhone X"
40
+ case "iPhone11,2": return "iPhone XS"
41
+ case "iPhone11,4", "iPhone11,6": return "iPhone XS Max"
42
+ case "iPhone11,8": return "iPhone XR"
43
+ case "iPhone12,1": return "iPhone 11"
44
+ case "iPhone12,3": return "iPhone 11 Pro"
45
+ case "iPhone12,5": return "iPhone 11 Pro Max"
46
+ case "iPhone13,1": return "iPhone 12 mini"
47
+ case "iPhone13,2": return "iPhone 12"
48
+ case "iPhone13,3": return "iPhone 12 Pro"
49
+ case "iPhone13,4": return "iPhone 12 Pro Max"
50
+ case "iPhone14,4": return "iPhone 13 mini"
51
+ case "iPhone14,5": return "iPhone 13"
52
+ case "iPhone14,2": return "iPhone 13 Pro"
53
+ case "iPhone14,3": return "iPhone 13 Pro Max"
54
+ case "iPhone14,7": return "iPhone 14"
55
+ case "iPhone14,8": return "iPhone 14 Plus"
56
+ case "iPhone15,2": return "iPhone 14 Pro"
57
+ case "iPhone15,3": return "iPhone 14 Pro Max"
58
+ case "iPhone8,4": return "iPhone SE"
59
+ case "iPhone12,8": return "iPhone SE (2nd generation)"
60
+ case "iPhone14,6": return "iPhone SE (3rd generation)"
61
+ case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4": return "iPad 2"
62
+ case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad (3rd generation)"
63
+ case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad (4th generation)"
64
+ case "iPad6,11", "iPad6,12": return "iPad (5th generation)"
65
+ case "iPad7,5", "iPad7,6": return "iPad (6th generation)"
66
+ case "iPad7,11", "iPad7,12": return "iPad (7th generation)"
67
+ case "iPad11,6", "iPad11,7": return "iPad (8th generation)"
68
+ case "iPad12,1", "iPad12,2": return "iPad (9th generation)"
69
+ case "iPad13,18", "iPad13,19": return "iPad (10th generation)"
70
+ case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air"
71
+ case "iPad5,3", "iPad5,4": return "iPad Air 2"
72
+ case "iPad11,3", "iPad11,4": return "iPad Air (3rd generation)"
73
+ case "iPad13,1", "iPad13,2": return "iPad Air (4th generation)"
74
+ case "iPad13,16", "iPad13,17": return "iPad Air (5th generation)"
75
+ case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad mini"
76
+ case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad mini 2"
77
+ case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad mini 3"
78
+ case "iPad5,1", "iPad5,2": return "iPad mini 4"
79
+ case "iPad11,1", "iPad11,2": return "iPad mini (5th generation)"
80
+ case "iPad14,1", "iPad14,2": return "iPad mini (6th generation)"
81
+ case "iPad6,3", "iPad6,4": return "iPad Pro (9.7-inch)"
82
+ case "iPad7,3", "iPad7,4": return "iPad Pro (10.5-inch)"
83
+ case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4": return "iPad Pro (11-inch) (1st generation)"
84
+ case "iPad8,9", "iPad8,10": return "iPad Pro (11-inch) (2nd generation)"
85
+ case "iPad13,4", "iPad13,5", "iPad13,6", "iPad13,7": return "iPad Pro (11-inch) (3rd generation)"
86
+ case "iPad14,3", "iPad14,4": return "iPad Pro (11-inch) (4th generation)"
87
+ case "iPad6,7", "iPad6,8": return "iPad Pro (12.9-inch) (1st generation)"
88
+ case "iPad7,1", "iPad7,2": return "iPad Pro (12.9-inch) (2nd generation)"
89
+ case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8": return "iPad Pro (12.9-inch) (3rd generation)"
90
+ case "iPad8,11", "iPad8,12": return "iPad Pro (12.9-inch) (4th generation)"
91
+ case "iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11": return "iPad Pro (12.9-inch) (5th generation)"
92
+ case "iPad14,5", "iPad14,6": return "iPad Pro (12.9-inch) (6th generation)"
93
+ case "AppleTV5,3": return "Apple TV"
94
+ case "AppleTV6,2": return "Apple TV 4K"
95
+ case "AudioAccessory1,1": return "HomePod"
96
+ case "AudioAccessory5,1": return "HomePod mini"
97
+ case "i386", "x86_64", "arm64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))"
98
+ default: return identifier
99
+ }
100
+ #elseif os(tvOS)
101
+ switch identifier {
102
+ case "AppleTV5,3": return "Apple TV 4"
103
+ case "AppleTV6,2": return "Apple TV 4K"
104
+ case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))"
105
+ default: return identifier
106
+ }
107
+ #endif
108
+ }
109
+
110
+ return mapToDevice(identifier: identifier)
111
+ }()
112
+ }
113
+ #endif
PersonalGPT/Reviews/SKSReviewManager.swift ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // SKSReviewManager.swift
3
+ // PrivateAIChat
4
+ //
5
+ // Created by jrb16 on 23/05/2023.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ import StoreKit
11
+ class SKSReviewManager {
12
+ private static let instance = SKSReviewManager()
13
+ static let openCountKey = "open_count_config"
14
+ static let replyCountKey = "reply_count_config"
15
+ static let totalGeneratedTextLengthKey = "generated_text_length_config"
16
+ static let lastVersionPromptedForReviewKey = "last_version_prompted_config"
17
+
18
+ var sharedInstance: SKSReviewManager {
19
+ .instance
20
+ }
21
+
22
+ static func incrementAppOpenCount() { // called from appdelegate didfinishLaunchingWithOptions:
23
+ let ud = UserDefaults.standard
24
+ var count = ud.integer(forKey: Self.openCountKey)
25
+ count += 1
26
+ ud.set(count, forKey: Self.openCountKey)
27
+ }
28
+
29
+ static func requestReview(generatedTextLength: Int) {
30
+ let ud = UserDefaults.standard
31
+ let count = ud.integer(forKey: Self.openCountKey)
32
+ let lastVersionPromptedForReview = ud.string(forKey: Self.lastVersionPromptedForReviewKey)
33
+
34
+ // Increment the number of replies
35
+ var replyCount = ud.integer(forKey: Self.replyCountKey)
36
+ replyCount += 1
37
+ ud.set(replyCount, forKey: Self.replyCountKey)
38
+
39
+ // Increment the generated text length
40
+ var totalGeneratedTextLength = ud.integer(forKey: Self.totalGeneratedTextLengthKey)
41
+ totalGeneratedTextLength += generatedTextLength
42
+ ud.set(totalGeneratedTextLength, forKey: Self.totalGeneratedTextLengthKey)
43
+
44
+ // Get the current bundle version for the app.
45
+ let infoDictionaryKey = kCFBundleVersionKey as String
46
+ guard let currentVersion = Bundle.main.object(forInfoDictionaryKey: infoDictionaryKey) as? String
47
+ else { fatalError("Expected to find a bundle version in the info dictionary.") }
48
+ // Verify the user completes the process several times and doesn’t receive a prompt for this app version.
49
+ if count >= 4, replyCount >= 8, totalGeneratedTextLength >= 256, currentVersion != lastVersionPromptedForReview, shouldRequestReview() {
50
+ Task { @MainActor [] in
51
+ // Delay for two seconds to avoid interrupting the person using the app.
52
+ // Use the equation n * 10^9 to convert seconds to nanoseconds.
53
+ try? await Task.sleep(nanoseconds: UInt64(2e9))
54
+
55
+ #if os(iOS)
56
+ let allScenes = UIApplication.shared.connectedScenes
57
+ let scene = allScenes.first { $0.activationState == .foregroundActive }
58
+
59
+ if let windowScene = scene as? UIWindowScene {
60
+ SKStoreReviewController.requestReview(in: windowScene)
61
+ UserDefaults.standard.set(currentVersion, forKey: Self.lastVersionPromptedForReviewKey)
62
+ }
63
+ #else
64
+ SKStoreReviewController.requestReview()
65
+ #endif
66
+ }
67
+ }
68
+ }
69
+
70
+ private static func shouldRequestReview() -> Bool {
71
+ #if os(iOS)
72
+ let verboteniPhones = ["iPhone XS", "iPhone XS Max", "iPhone XR", "iPhone 11", "iPhone 11 Pro", "iPhone 11 Pro Max", "iPhone 12 mini", "iPhone 12", "iPhone 12 Pro", "iPhone 12 Pro Max"]
73
+ let verboteniPads = ["iPad (8th generation)", "iPad mini (5th generation)", "iPad Air (3rd generation)"]
74
+ let modelName = UIDevice.modelName
75
+ if verboteniPhones.contains(modelName) || verboteniPads.contains(modelName) {
76
+ return false
77
+ }
78
+ #endif
79
+ return true
80
+ }
81
+ }
redpajama/ChatBackend.mm CHANGED
@@ -442,10 +442,21 @@ CPPChatBackend::~CPPChatBackend() {
442
  backend->decode(temperature, topK, topP, enable_mirostat);
443
  }
444
 
 
 
 
 
 
 
 
 
 
445
  - (NSString*)getMessage {
446
  CPPChatBackend* backend = [self getBackendInstance];
447
  std::string message = backend->getMessage();
448
- return [NSString stringWithUTF8String:message.c_str()];
 
 
449
  }
450
 
451
  - (bool)stopped {
 
442
  backend->decode(temperature, topK, topP, enable_mirostat);
443
  }
444
 
445
+ - (NSString *)removeSuffixes:(NSArray *)suffixes fromString:(NSString *)string {
446
+ for (NSString *suffix in suffixes) {
447
+ if ([string hasSuffix:suffix]) {
448
+ string = [string substringToIndex:string.length - suffix.length];
449
+ }
450
+ }
451
+ return string;
452
+ }
453
+
454
  - (NSString*)getMessage {
455
  CPPChatBackend* backend = [self getBackendInstance];
456
  std::string message = backend->getMessage();
457
+ NSString* msg = [NSString stringWithUTF8String:message.c_str()];
458
+ NSArray *suffixes = @[@"\n", @"<human", @"<human>", @"<bot", @"<bot>"];
459
+ return [self removeSuffixes:suffixes fromString:msg];
460
  }
461
 
462
  - (bool)stopped {