Skip to content

Commit

Permalink
In-App updates (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
voltangle authored Aug 3, 2022
1 parent 521fbbc commit e119098
Show file tree
Hide file tree
Showing 21 changed files with 141 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import TDLibKit
import Foundation
import Combine

// swiftlint:disable function_body_length
// swiftlint:disable all
public class MockChatService: ChatService {
public var updateSubject = PassthroughSubject<Update, Never>()

Expand Down
2 changes: 1 addition & 1 deletion Backend/Sources/Backend/Services/Td/TdChatService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import TDLibKit
import Logs
import UniformTypeIdentifiers

// swiftlint:disable type_body_length function_body_length
// swiftlint:disable function_body_length
public class TdChatService: ChatService {
public var updateSubject: PassthroughSubject<Update, Never> {
tdApi.client.updateSubject
Expand Down
39 changes: 31 additions & 8 deletions Moc.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
434A60802848AA000086B866 /* ChatPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434A607F2848AA000086B866 /* ChatPickerView.swift */; };
4360D6E3283FE2BE00D3378F /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 4360D6E2283FE2BE00D3378F /* Collections */; };
4360D6E5283FE2BE00D3378F /* DequeModule in Frameworks */ = {isa = PBXBuildFile; productRef = 4360D6E4283FE2BE00D3378F /* DequeModule */; };
4360D6E7283FE2BE00D3378F /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 4360D6E6283FE2BE00D3378F /* OrderedCollections */; };
4360D6E7283FE2BE00D3378F /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 4360D6E6283FE2BE00D3378F /* OrderedCollections */; settings = {ATTRIBUTES = (Required, ); }; };
4367071F2861A6CD00587A63 /* QuickLookPreviewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4367071E2861A6CD00587A63 /* QuickLookPreviewWrapper.swift */; platformFilter = ios; };
436707212861A8A500587A63 /* QuickLookPreviewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436707202861A8A500587A63 /* QuickLookPreviewItem.swift */; platformFilter = ios; };
436707232861A8CA00587A63 /* View+QuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436707222861A8CA00587A63 /* View+QuickLook.swift */; platformFilter = ios; };
Expand Down Expand Up @@ -85,7 +85,7 @@
43807DA527E2137A0056A3D3 /* Resolver in Frameworks */ = {isa = PBXBuildFile; productRef = 43807DA427E2137A0056A3D3 /* Resolver */; };
43807DA827E2138A0056A3D3 /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = 43807DA727E2138A0056A3D3 /* Lottie */; };
43807DAB27E2139B0056A3D3 /* AlertToast in Frameworks */ = {isa = PBXBuildFile; productRef = 43807DAA27E2139B0056A3D3 /* AlertToast */; };
43807DB827E214440056A3D3 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 43807DB727E214440056A3D3 /* Introspect */; };
43807DB827E214440056A3D3 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 43807DB727E214440056A3D3 /* Introspect */; settings = {ATTRIBUTES = (Required, ); }; };
43807DBC27E214970056A3D3 /* Backend in Frameworks */ = {isa = PBXBuildFile; productRef = 43807DBB27E214970056A3D3 /* Backend */; };
43807DC727E214E50056A3D3 /* libc++.1.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 43807DC527E214D30056A3D3 /* libc++.1.tbd */; };
43807DC827E214E90056A3D3 /* libz.1.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 43807DC627E214DD0056A3D3 /* libz.1.tbd */; };
Expand Down Expand Up @@ -120,13 +120,15 @@
43B1029928820A82009FCF53 /* Acknowledgment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43B1029828820A82009FCF53 /* Acknowledgment.swift */; };
43B1029B28831A8D009FCF53 /* Image+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43B1029A28831A8D009FCF53 /* Image+Data.swift */; };
43B1029D288336E0009FCF53 /* ChatType+IsGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43B1029C288336E0009FCF53 /* ChatType+IsGroup.swift */; };
43B5D7BB28996D4600180E65 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 43B5D7BA28996D4600180E65 /* Sparkle */; };
43B5D7BE28996ED000180E65 /* UpdateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D7BD28996DF300180E65 /* UpdateManager.swift */; };
43BFD915285CC2B000D8980A /* MultilineTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFD914285CC2B000D8980A /* MultilineTextField.swift */; platformFilter = ios; };
43BFD917285CC30B00D8980A /* MultilineTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFD916285CC30B00D8980A /* MultilineTextField.swift */; platformFilters = (macos, ); };
43BFD91C285D148100D8980A /* NWPathMonitor+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFD91B285D148100D8980A /* NWPathMonitor+Combine.swift */; };
43C0F49A285A58BD009F2419 /* View+SidebarSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C0F499285A58BD009F2419 /* View+SidebarSize.swift */; };
43C0F49D285A68ED009F2419 /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = 43C0F49C285A68ED009F2419 /* Defaults */; };
43C0F4A0285A69AA009F2419 /* FolderLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C0F49F285A69AA009F2419 /* FolderLayout.swift */; };
43C29C02287D7FEC00D10AB8 /* TDLibKit in Frameworks */ = {isa = PBXBuildFile; productRef = 43C29C01287D7FEC00D10AB8 /* TDLibKit */; };
43C29C02287D7FEC00D10AB8 /* TDLibKit in Frameworks */ = {isa = PBXBuildFile; productRef = 43C29C01287D7FEC00D10AB8 /* TDLibKit */; settings = {ATTRIBUTES = (Required, ); }; };
43C29C04287D8D9E00D10AB8 /* Animation+FastStartSlowStop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C29C03287D8D9E00D10AB8 /* Animation+FastStartSlowStop.swift */; };
43EC18DA2856208A00FCAD43 /* libSystem.B.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 43EC18D92856207C00FCAD43 /* libSystem.B.tbd */; platformFilter = ios; };
43EC18DC285620AF00FCAD43 /* libc++abi.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 43EC18DB285620A800FCAD43 /* libc++abi.tbd */; platformFilter = ios; };
Expand Down Expand Up @@ -250,6 +252,7 @@
43B1029828820A82009FCF53 /* Acknowledgment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Acknowledgment.swift; sourceTree = "<group>"; };
43B1029A28831A8D009FCF53 /* Image+Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Image+Data.swift"; sourceTree = "<group>"; };
43B1029C288336E0009FCF53 /* ChatType+IsGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChatType+IsGroup.swift"; sourceTree = "<group>"; };
43B5D7BD28996DF300180E65 /* UpdateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateManager.swift; sourceTree = "<group>"; };
43BFD914285CC2B000D8980A /* MultilineTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineTextField.swift; sourceTree = "<group>"; };
43BFD916285CC30B00D8980A /* MultilineTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineTextField.swift; sourceTree = "<group>"; };
43BFD91B285D148100D8980A /* NWPathMonitor+Combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NWPathMonitor+Combine.swift"; sourceTree = "<group>"; };
Expand All @@ -276,20 +279,21 @@
43016AA92842DE3000C219B4 /* Caching in Frameworks */,
431215542858E50B009EFEB5 /* Numerics in Frameworks */,
43A9637B2868C8AD0076F5FD /* SkeletonUI in Frameworks */,
43B5D7BB28996D4600180E65 /* Sparkle in Frameworks */,
4360D6E3283FE2BE00D3378F /* Collections in Frameworks */,
43C0F49D285A68ED009F2419 /* Defaults in Frameworks */,
4360D6E5283FE2BE00D3378F /* DequeModule in Frameworks */,
434203B8283CB01D003E344C /* Algorithms in Frameworks */,
431215562858E50B009EFEB5 /* RealModule in Frameworks */,
43807DA827E2138A0056A3D3 /* Lottie in Frameworks */,
2D229DD7287606710056A294 /* Networking in Frameworks */,
43807DC827E214E90056A3D3 /* libz.1.tbd in Frameworks */,
43807DBC27E214970056A3D3 /* Backend in Frameworks */,
431215522858E50B009EFEB5 /* ComplexModule in Frameworks */,
43807DC827E214E90056A3D3 /* libz.1.tbd in Frameworks */,
43807DC727E214E50056A3D3 /* libc++.1.tbd in Frameworks */,
43EC18DA2856208A00FCAD43 /* libSystem.B.tbd in Frameworks */,
43EC18DC285620AF00FCAD43 /* libc++abi.tbd in Frameworks */,
4360D6E7283FE2BE00D3378F /* OrderedCollections in Frameworks */,
43807DC727E214E50056A3D3 /* libc++.1.tbd in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -398,6 +402,7 @@
43807D4A27E213350056A3D3 /* Models */,
43807D7827E213350056A3D3 /* ViewModels */,
43807D5527E213350056A3D3 /* Views */,
43807D6C27E213350056A3D3 /* Commands */,
43807D7427E213350056A3D3 /* SwiftGen */,
43807D5027E213350056A3D3 /* MocApp+Injection.swift */,
43807D5127E213350056A3D3 /* Assets.xcassets */,
Expand Down Expand Up @@ -436,7 +441,6 @@
isa = PBXGroup;
children = (
43807D5627E213350056A3D3 /* Settings */,
43807D6C27E213350056A3D3 /* Commands */,
433EDD982860EB90009D03D5 /* AsyncTd */,
43807D6327E213350056A3D3 /* Chat */,
439BA4262863C11400339375 /* Login */,
Expand Down Expand Up @@ -503,6 +507,7 @@
isa = PBXGroup;
children = (
439E0E23287EDEDC00013A0F /* About */,
43B5D7BD28996DF300180E65 /* UpdateManager.swift */,
43807D6D27E213350056A3D3 /* AppCommands.swift */,
);
path = Commands;
Expand Down Expand Up @@ -677,6 +682,7 @@
43A9637A2868C8AD0076F5FD /* SkeletonUI */,
2D229DD6287606710056A294 /* Networking */,
43C29C01287D7FEC00D10AB8 /* TDLibKit */,
43B5D7BA28996D4600180E65 /* Sparkle */,
);
productName = Moc;
productReference = 43807CF527E1FCEC0056A3D3 /* Moc.app */;
Expand Down Expand Up @@ -740,6 +746,7 @@
43C0F49B285A68ED009F2419 /* XCRemoteSwiftPackageReference "Defaults" */,
43A963792868C8AD0076F5FD /* XCRemoteSwiftPackageReference "SkeletonUI" */,
43C29C00287D7FEC00D10AB8 /* XCRemoteSwiftPackageReference "tdlibkit" */,
43B5D7B928996D4500180E65 /* XCRemoteSwiftPackageReference "Sparkle" */,
);
productRefGroup = 43807CF627E1FCEC0056A3D3 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -880,6 +887,7 @@
4312154D2858C326009EFEB5 /* GenerateQRCode.swift in Sources */,
434A07172869003200A2BBA5 /* AVPlayerViewWrapper.swift in Sources */,
433EDD942860E7CB009D03D5 /* QuickLookPreviewWrapper.swift in Sources */,
43B5D7BE28996ED000180E65 /* UpdateManager.swift in Sources */,
43807D8227E213350056A3D3 /* ChatType.swift in Sources */,
43807D9C27E213350056A3D3 /* ContentView.swift in Sources */,
43051C9B28779AE2003C5CE2 /* ChatViewModel+Updates.swift in Sources */,
Expand Down Expand Up @@ -1050,11 +1058,12 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 11;
CURRENT_PROJECT_VERSION = 12;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "Shared/Preview\\ Assets.xcassets";
DEVELOPMENT_TEAM = 9H3XZRTVLY;
ENABLE_HARDENED_RUNTIME = YES;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Shared/Info.plist;
Expand Down Expand Up @@ -1092,11 +1101,12 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 11;
CURRENT_PROJECT_VERSION = 12;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "Shared/Preview\\ Assets.xcassets";
DEVELOPMENT_TEAM = 9H3XZRTVLY;
ENABLE_HARDENED_RUNTIME = YES;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Shared/Info.plist;
Expand Down Expand Up @@ -1258,6 +1268,14 @@
minimumVersion = 1.0.0;
};
};
43B5D7B928996D4500180E65 /* XCRemoteSwiftPackageReference "Sparkle" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sparkle-project/Sparkle.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.0.0;
};
};
43C0F49B285A68ED009F2419 /* XCRemoteSwiftPackageReference "Defaults" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sindresorhus/Defaults.git";
Expand Down Expand Up @@ -1349,6 +1367,11 @@
package = 43A963792868C8AD0076F5FD /* XCRemoteSwiftPackageReference "SkeletonUI" */;
productName = SkeletonUI;
};
43B5D7BA28996D4600180E65 /* Sparkle */ = {
isa = XCSwiftPackageProductDependency;
package = 43B5D7B928996D4500180E65 /* XCRemoteSwiftPackageReference "Sparkle" */;
productName = Sparkle;
};
43C0F49C285A68ED009F2419 /* Defaults */ = {
isa = XCSwiftPackageProductDependency;
package = 43C0F49B285A68ED009F2419 /* XCRemoteSwiftPackageReference "Defaults" */;
Expand Down
3 changes: 2 additions & 1 deletion Moc.xcodeproj/xcshareddata/xcschemes/Moc.xcscheme
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
version = "1.3">
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
Expand Down Expand Up @@ -48,6 +48,7 @@
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugXPCServices = "NO"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
Expand Down
2 changes: 0 additions & 2 deletions Networking/Sources/Networking/Base/HTTPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@
//
import Foundation


public protocol HTTPClient {
func sendRequest<T: Decodable>(
endpoint: Endpoint,
responseModel: T.Type
) async throws -> T
}


public extension HTTPClient {
func sendRequest<T: Decodable>(
endpoint: Endpoint,
Expand Down
1 change: 0 additions & 1 deletion Networking/Sources/Networking/Base/RequestError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// Created by DariaMikots on 06.07.2022.
//


public enum RequestError: Error {
case decode
case invalidURL
Expand Down
11 changes: 5 additions & 6 deletions Networking/Tests/NetworkingTests/EmojiTests/EmojiMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
import Foundation
import Networking


final class EmojiServiceMock: Mockable, EmojiServiceable {
func getEmoji(
_ name: String,
_ length: String) async throws -> Emoji {
return loadJSON(filename: "emoji",
type: Emoji.self
)
}
_ length: String
) async throws -> Emoji {
return loadJSON(filename: "emoji",
type: Emoji.self)
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ struct AboutView: View {
VStack {
Text("Acknowledgments")
.font(.system(size: 40, weight: .medium, design: .default))
Link("**Technoblade never dies**", destination: URL(string: "https://www.curesarcoma.org/technoblade-tribute/")!)
Link(
"**Technoblade never dies**",
destination: URL(string: "https://www.curesarcoma.org/technoblade-tribute/")!)
Divider()
ForEach(acknowledgmentList, id: \.self) { list in
Link(list.name, destination: list.url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@

import SwiftUI

struct AppCommands: Commands {
struct AppCommands: Commands {
@ObservedObject var updateManager: UpdateManager

var body: some Commands {
CommandGroup(after: .appInfo) {
Button("Check for updates...", action: updateManager.checkForUpdates)
.disabled(!updateManager.canCheckForUpdates)
}
CommandGroup(after: .appSettings) {
Button(action: {

}, label: {
Image(systemName: "bookmark")
Text("Saved messages")
Expand Down
37 changes: 37 additions & 0 deletions Shared/Commands/UpdateManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// UpdateManager.swift
// Moc
//
// Created by Егор Яковенко on 02.08.2022.
//

import Combine
import Sparkle
import Utilities

class UpdateManager: ObservableObject {
private let updaterController: SPUStandardUpdaterController

@Published var canCheckForUpdates = false

init() {
// If you want to start the updater manually, pass false to startingUpdater and call .startUpdater() later
// This is where you can also pass an updater delegate if you need one
updaterController = SPUStandardUpdaterController(
startingUpdater: true,
updaterDelegate: nil,
userDriverDelegate: nil)

updaterController.updater.checkForUpdatesInBackground()

updaterController.updater.setFeedURL(
URL(string: "https://api.appcenter.ms/v0.1/public/sparkle/apps/\(Secret.appCenterSecret)"))

updaterController.updater.publisher(for: \.canCheckForUpdates)
.assign(to: &$canCheckForUpdates)
}

func checkForUpdates() {
updaterController.checkForUpdates(nil)
}
}
2 changes: 2 additions & 0 deletions Shared/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
</array>
</dict>
</array>
<key>SUEnableInstallerLauncherService</key>
<true/>
</dict>
</plist>
7 changes: 7 additions & 0 deletions Shared/Moc.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)-spks</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)-spki</string>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.assets.movies.read-write</key>
Expand All @@ -22,6 +27,8 @@
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.personal-information.addressbook</key>
<true/>
<key>com.apple.security.personal-information.location</key>
<true/>
</dict>
Expand Down
11 changes: 10 additions & 1 deletion Shared/MocApp+Injection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
// Created by Егор Яковенко on 24.12.2021.
//

// import AppCenter
// import AppCenterAnalytics
// import AppCenterCrashes
import Backend
import CryptoKit
import Resolver
Expand Down Expand Up @@ -36,6 +39,7 @@ public extension Resolver {
@main
struct MocApp: App {
@Environment(\.scenePhase) var scenePhase
@StateObject var updateManager = UpdateManager()

init() {
Resolver.registerUI()
Expand All @@ -44,6 +48,11 @@ struct MocApp: App {
client: TdClientImpl(completionQueue: .global())
))
TdApi.shared[0].startTdLibUpdateHandler()

// AppCenter.start(withAppSecret: Secret.appCenterSecret, services: [
// Analytics.self,
// Crashes.self
// ])
}

#if os(macOS)
Expand Down Expand Up @@ -88,7 +97,7 @@ struct MocApp: App {
}
.commands {
aboutCommand
AppCommands()
AppCommands(updateManager: updateManager)
}

#if os(macOS)
Expand Down
1 change: 1 addition & 0 deletions Shared/ViewModels/Chat/ChatViewModel+Updates.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import TDLibKit
import Utilities

extension ChatViewModel {
// swiftlint:disable function_body_length
func updateNewMessage(_ update: UpdateNewMessage) {
logger.debug("UpdateNewMessage")
let tdMessage = update.message
Expand Down
Loading

0 comments on commit e119098

Please sign in to comment.