diff --git a/ConversationsClassic/AppData/Client/Client.swift b/ConversationsClassic/AppData/Client/Client.swift new file mode 100644 index 0000000..3584db6 --- /dev/null +++ b/ConversationsClassic/AppData/Client/Client.swift @@ -0,0 +1,116 @@ +import Combine +import Foundation +import Martin + +enum ClientState: Equatable { + enum ClientConnectionState { + case connected + case disconnected + } + + case disabled + case enabled(ClientConnectionState) +} + +final class Client: ObservableObject { + @Published private(set) var state: ClientState = .enabled(.disconnected) + @Published private(set) var credentials: Credentials + + private var connection: XMPPClient + private var connectionCancellable: AnyCancellable? + + private var rosterManager = RosterManager() + + init(credentials: Credentials) { + self.credentials = credentials + state = credentials.isActive ? .enabled(.disconnected) : .disabled + connection = Self.prepareConnection(credentials, rosterManager) + connectionCancellable = connection.$state + .sink { [weak self] state in + guard let self = self else { return } + guard self.credentials.isActive else { + self.state = .disabled + return + } + switch state { + case .connected: + self.state = .enabled(.connected) + + default: + self.state = .enabled(.disconnected) + } + } + } + + func addRoster(_ roster: Roster) async throws { + _ = try await connection.module(.roster).addItem( + jid: JID(roster.contactBareJid), + name: roster.name, + groups: roster.data.groups + ) + } + + func deleteRoster(_ roster: Roster) async throws { + _ = try await connection.module(.roster).removeItem(jid: JID(roster.contactBareJid)) + } +} + +extension Client { + enum ClientLoginResult { + case success(Client) + case failure + } + + static func tryLogin(with credentials: Credentials) async -> ClientLoginResult { + let client = Client(credentials: credentials) + do { + try await client.connection.loginAndWait() + return .success(client) + } catch { + return .failure + } + } +} + +private extension Client { + static func prepareConnection(_ credentials: Credentials, _ roster: RosterManager) -> XMPPClient { + let client = XMPPClient() + + // register modules + // core modules RFC 6120 + client.modulesManager.register(StreamFeaturesModule()) + client.modulesManager.register(SaslModule()) + client.modulesManager.register(AuthModule()) + client.modulesManager.register(SessionEstablishmentModule()) + client.modulesManager.register(ResourceBinderModule()) + client.modulesManager.register(DiscoveryModule(identity: .init(category: "client", type: "iOS", name: Const.appName))) + + // messaging modules RFC 6121 + client.modulesManager.register(RosterModule(rosterManager: roster)) + client.modulesManager.register(PresenceModule()) + + // client.modulesManager.register(PubSubModule()) + // client.modulesManager.register(MessageModule(chatManager: manager)) + // client.modulesManager.register(MessageArchiveManagementModule()) + + // client.modulesManager.register(MessageCarbonsModule()) + + // file transfer modules + // client.modulesManager.register(HttpFileUploadModule()) + + // extensions + client.modulesManager.register(SoftwareVersionModule()) + client.modulesManager.register(PingModule()) + client.connectionConfiguration.userJid = .init(credentials.bareJid) + client.connectionConfiguration.credentials = .password(password: credentials.pass) + + // group chats + // client.modulesManager.register(MucModule(roomManager: manager)) + + // channels + // client.modulesManager.register(MixModule(channelManager: manager)) + + // add client to clients + return client + } +} diff --git a/ConversationsClassic/AppData/Client/RosterManager.swift b/ConversationsClassic/AppData/Client/RosterManager.swift new file mode 100644 index 0000000..272732d --- /dev/null +++ b/ConversationsClassic/AppData/Client/RosterManager.swift @@ -0,0 +1,152 @@ +import Foundation +import GRDB +import Martin + +final class RosterManager: Martin.RosterManager { + func clear(for context: Martin.Context) { + do { + try Database.shared.dbQueue.write { db in + try Roster + .filter(Column("bareJid") == context.userBareJid.stringValue) + .deleteAll(db) + + try RosterVersion + .filter(Column("bareJid") == context.userBareJid.stringValue) + .deleteAll(db) + } + } catch { + logIt(.error, "Error clearing roster: \(error.localizedDescription)") + } + } + + func items(for context: Martin.Context) -> [any Martin.RosterItemProtocol] { + do { + let rosters: [Roster] = try Database.shared.dbQueue.read { db in + try Roster.filter(Column("bareJid") == context.userBareJid.stringValue).fetchAll(db) + } + return rosters.map { roster in + RosterItemBase( + jid: JID(roster.bareJid), + name: roster.name, + subscription: RosterItemSubscription(rawValue: roster.subscription) ?? .none, + groups: roster.data.groups, + ask: roster.ask, + annotations: roster.data.annotations + ) + } + } catch { + logIt(.error, "Error fetching roster items: \(error.localizedDescription)") + return [] + } + } + + func item(for context: Martin.Context, jid: Martin.JID) -> (any Martin.RosterItemProtocol)? { + do { + let roster: Roster? = try Database.shared.dbQueue.read { db in + try Roster + .filter(Column("bareJid") == context.userBareJid.stringValue) + .filter(Column("contactBareJid") == jid.stringValue) + .fetchOne(db) + } + if let roster { + return RosterItemBase( + jid: JID(roster.bareJid), + name: roster.name, + subscription: RosterItemSubscription(rawValue: roster.subscription) ?? .none, + groups: roster.data.groups, + ask: roster.ask, + annotations: roster.data.annotations + ) + } else { + return nil + } + } catch { + logIt(.error, "Error fetching roster item: \(error.localizedDescription)") + return nil + } + } + + func updateItem(for context: Martin.Context, jid: Martin.JID, name: String?, subscription: Martin.RosterItemSubscription, groups: [String], ask: Bool, annotations: [Martin.RosterItemAnnotation]) -> (any Martin.RosterItemProtocol)? { + do { + let roster = Roster( + bareJid: context.userBareJid.stringValue, + contactBareJid: jid.stringValue, + name: name, + subscription: subscription.rawValue, + ask: ask, + data: DBRosterData( + groups: groups, + annotations: annotations + ) + ) + try Database.shared.dbQueue.write { db in + try roster.save(db) + } + return RosterItemBase(jid: jid, name: name, subscription: subscription, groups: groups, ask: ask, annotations: annotations) + } catch { + logIt(.error, "Error updating roster item: \(error.localizedDescription)") + return nil + } + } + + func deleteItem(for context: Martin.Context, jid: Martin.JID) -> (any Martin.RosterItemProtocol)? { + do { + let roster: Roster? = try Database.shared.dbQueue.read { db in + try Roster + .filter(Column("bareJid") == context.userBareJid.stringValue) + .filter(Column("contactBareJid") == jid.stringValue) + .fetchOne(db) + } + if let roster { + _ = try Database.shared.dbQueue.write { db in + try roster.delete(db) + } + return RosterItemBase( + jid: JID(roster.bareJid), + name: roster.name, + subscription: RosterItemSubscription(rawValue: roster.subscription) ?? .none, + groups: roster.data.groups, + ask: roster.ask, + annotations: roster.data.annotations + ) + } else { + return nil + } + } catch { + logIt(.error, "Error fetching roster version: \(error.localizedDescription)") + return nil + } + } + + func version(for context: Martin.Context) -> String? { + do { + let version: RosterVersion? = try Database.shared.dbQueue.read { db in + try RosterVersion + .filter(Column("bareJid") == context.userBareJid.stringValue) + .fetchOne(db) + } + return version?.version + } catch { + logIt(.error, "Error fetching roster version: \(error.localizedDescription)") + return nil + } + } + + func set(version: String?, for context: Martin.Context) { + guard let version else { return } + do { + try Database.shared.dbQueue.write { db in + let rosterVersion = RosterVersion( + bareJid: context.userBareJid.stringValue, + version: version + ) + try rosterVersion.save(db) + } + } catch { + logIt(.error, "Error setting roster version: \(error.localizedDescription)") + } + } + + func initialize(context _: Martin.Context) {} + func deinitialize(context _: Martin.Context) {} +} diff --git a/ConversationsClassic/AppData/Model/Credentials.swift b/ConversationsClassic/AppData/Model/Credentials.swift new file mode 100644 index 0000000..06ab1a9 --- /dev/null +++ b/ConversationsClassic/AppData/Model/Credentials.swift @@ -0,0 +1,33 @@ +import Combine +import Foundation +import GRDB +import SwiftUI + +struct Credentials: DBStorable, Hashable { + static let databaseTableName = "credentials" + + var id: String { bareJid } + var bareJid: String + var pass: String + var isActive: Bool + + func save() async throws { + let db = Database.shared.dbQueue + try await db.write { db in + try self.save(db) + } + } + + func delete() async throws { + let db = Database.shared.dbQueue + _ = try await db.write { db in + try self.delete(db) + } + } +} + +// extension Account: UniversalInputSelectionElement { +// var text: String? { bareJid } +// var icon: Image? { nil } +// } +// diff --git a/ConversationsClassic/AppData/Model/Roster.swift b/ConversationsClassic/AppData/Model/Roster.swift new file mode 100644 index 0000000..44cc474 --- /dev/null +++ b/ConversationsClassic/AppData/Model/Roster.swift @@ -0,0 +1,71 @@ +import Foundation +import GRDB +import Martin + +struct RosterVersion: DBStorable { + static let databaseTableName = "rosterVersions" + + var bareJid: String + var version: String + var id: String { bareJid } +} + +struct Roster: DBStorable { + static let databaseTableName = "rosters" + + var bareJid: String = "" + var contactBareJid: String + var name: String? + var subscription: String + var ask: Bool + var data: DBRosterData + var locallyDeleted: Bool = false + + var id: String { "\(bareJid)-\(contactBareJid)" } +} + +struct DBRosterData: Codable, DatabaseValueConvertible { + let groups: [String] + let annotations: [RosterItemAnnotation] + + public var databaseValue: DatabaseValue { + let encoder = JSONEncoder() + // swiftlint:disable:next force_try + let data = try! encoder.encode(self) + return data.databaseValue + } + + public static func fromDatabaseValue(_ dbValue: DatabaseValue) -> Self? { + guard let data = Data.fromDatabaseValue(dbValue) else { + return nil + } + let decoder = JSONDecoder() + // swiftlint:disable:next force_try + return try! decoder.decode(Self.self, from: data) + } + + static func == (lhs: DBRosterData, rhs: DBRosterData) -> Bool { + lhs.groups == rhs.groups && lhs.annotations == rhs.annotations + } +} + +extension RosterItemAnnotation: Equatable { + public static func == (lhs: RosterItemAnnotation, rhs: RosterItemAnnotation) -> Bool { + lhs.type == rhs.type && lhs.values == rhs.values + } +} + +extension Roster: Equatable { + static func == (lhs: Roster, rhs: Roster) -> Bool { + lhs.bareJid == rhs.bareJid && lhs.contactBareJid == rhs.contactBareJid + } +} + +extension Roster { + static func fetchAll(for jid: String) async throws -> [Roster] { + let rosters = try await Database.shared.dbQueue.read { db in + try Roster.filter(Column("bareJid") == jid).fetchAll(db) + } + return rosters + } +} diff --git a/ConversationsClassic/AppData/Services/Database+Migrations.swift b/ConversationsClassic/AppData/Services/Database+Migrations.swift new file mode 100644 index 0000000..caf742d --- /dev/null +++ b/ConversationsClassic/AppData/Services/Database+Migrations.swift @@ -0,0 +1,42 @@ +import Foundation +import GRDB + +extension Database { + static var migrator: DatabaseMigrator = { + var migrator = DatabaseMigrator() + + // flush db on schema change (only in DEV mode) + #if DEBUG + migrator.eraseDatabaseOnSchemaChange = true + #endif + + // 1st migration - basic tables + migrator.registerMigration("Add basic tables") { db in + // credentials + try db.create(table: "credentials", options: [.ifNotExists]) { table in + table.column("bareJid", .text).notNull().primaryKey().unique(onConflict: .replace) + table.column("pass", .text).notNull() + table.column("isActive", .boolean).notNull().defaults(to: true) + } + + // rosters + try db.create(table: "rosterVersions", options: [.ifNotExists]) { table in + table.column("bareJid", .text).notNull().primaryKey().unique(onConflict: .replace) + table.column("version", .text).notNull() + } + try db.create(table: "rosters", options: [.ifNotExists]) { table in + table.column("bareJid", .text).notNull() + table.column("contactBareJid", .text).notNull() + table.column("name", .text) + table.column("subscription", .text).notNull() + table.column("ask", .boolean).notNull().defaults(to: false) + table.column("data", .text).notNull() + table.primaryKey(["bareJid", "contactBareJid"], onConflict: .replace) + table.column("locallyDeleted", .boolean).notNull().defaults(to: false) + } + } + + // return migrator + return migrator + }() +} diff --git a/ConversationsClassic/AppData/Services/Database.swift b/ConversationsClassic/AppData/Services/Database.swift new file mode 100644 index 0000000..5b2d77c --- /dev/null +++ b/ConversationsClassic/AppData/Services/Database.swift @@ -0,0 +1,55 @@ +import Combine +import Foundation +import GRDB +import SwiftUI + +// MARK: - Models protocol +typealias DBStorable = Codable & FetchableRecord & Identifiable & PersistableRecord & TableRecord + +// MARK: - Database init +final class Database { + static let shared = Database() + let dbQueue: DatabaseQueue + + private init() { + do { + // Create db folder if not exists + let fileManager = FileManager.default + let appSupportURL = try fileManager.url( + for: .applicationSupportDirectory, in: .userDomainMask, + appropriateFor: nil, create: true + ) + let directoryURL = appSupportURL.appendingPathComponent("ConversationsClassic", isDirectory: true) + try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true) + + // Open or create the database + let databaseURL = directoryURL.appendingPathComponent("db.sqlite") + dbQueue = try DatabaseQueue(path: databaseURL.path, configuration: Database.config) + + // Some debug info + #if DEBUG + print("Database path: \(databaseURL.path)") + #endif + + // Apply migrations + try Database.migrator.migrate(dbQueue) + } catch { + fatalError("Database initialization failed: \(error)") + } + } +} + +// MARK: - Config +private extension Database { + static let config: Configuration = { + var config = Configuration() + #if DEBUG + // verbose and debugging in DEBUG builds only. + config.publicStatementArguments = true + config.prepareDatabase { db in + db.trace { print("SQL> \($0)\n") } + } + #endif + return config + }() +} diff --git a/ConversationsClassic/AppData/Services/Logger.swift b/ConversationsClassic/AppData/Services/Logger.swift new file mode 100644 index 0000000..6e69c34 --- /dev/null +++ b/ConversationsClassic/AppData/Services/Logger.swift @@ -0,0 +1,42 @@ +import Combine +import Foundation +import SwiftUI + +let isConsoleLoggingEnabled = false + +enum LogLevels: String { + case info = "\u{F449}" + case warning = "\u{F071}" + case error = "\u{EA76}" +} + +// For database errors logging +func logIt(_ level: LogLevels, _ message: String) { + #if DEBUG + let timeStr = dateFormatter.string(from: Date()) + let str = "\(timeStr) \(level.rawValue) \(message)" + print(str) + if isConsoleLoggingEnabled { + NSLog(str) + } + #endif +} + +private var dateFormatter: DateFormatter { + let formatter = DateFormatter() + formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale + formatter.dateFormat = "MM-dd HH:mm:ss.SSS" + return formatter +} + +// For thread debugging +func ptInfo(_ message: String) { + #if DEBUG + let timeStr = dateFormatter.string(from: Date()) + let str = "\(timeStr) \(message) -> \(Thread.current), \(String(validatingUTF8: __dispatch_queue_get_label(nil)) ?? "no queue label")" + print(str) + if isConsoleLoggingEnabled { + NSLog(str) + } + #endif +} diff --git a/ConversationsClassic/AppData/Services/NetworkMonitor.swift b/ConversationsClassic/AppData/Services/NetworkMonitor.swift new file mode 100644 index 0000000..005bd5e --- /dev/null +++ b/ConversationsClassic/AppData/Services/NetworkMonitor.swift @@ -0,0 +1,37 @@ +import Combine +import Network + +extension NWPathMonitor { + func paths() -> AsyncStream { + AsyncStream { continuation in + pathUpdateHandler = { path in + continuation.yield(path) + } + continuation.onTermination = { [weak self] _ in + self?.cancel() + } + start(queue: DispatchQueue(label: "NSPathMonitor.paths")) + } + } +} + +final actor NetworkMonitor: ObservableObject { + static let shared = NetworkMonitor() + + @Published private(set) var isOnline: Bool = false + + private let monitor = NWPathMonitor() + + init() { + Task(priority: .background) { + await startMonitoring() + } + } + + func startMonitoring() async { + let monitor = NWPathMonitor() + for await path in monitor.paths() { + isOnline = path.status == .satisfied + } + } +} diff --git a/ConversationsClassic/AppData/Stores/ClientsStore.swift b/ConversationsClassic/AppData/Stores/ClientsStore.swift new file mode 100644 index 0000000..7925984 --- /dev/null +++ b/ConversationsClassic/AppData/Stores/ClientsStore.swift @@ -0,0 +1,41 @@ +import Combine +import Foundation +import GRDB + +@MainActor +final class ClientsStore: ObservableObject { + static let shared = ClientsStore() + + @Published private(set) var ready = false + @Published private(set) var clients: [Client] = [] + + func startFetching() { + Task { + let observation = ValueObservation.tracking(Credentials.fetchAll) + do { + for try await credentials in observation.values(in: Database.shared.dbQueue) { + processCredentials(credentials) + ready = true + print("Fetched \(credentials.count) credentials") + } + } catch {} + } + } + + func addNewClient(_ client: Client) { + clients.append(client) + Task(priority: .background) { + try? await client.credentials.save() + } + } + + private func processCredentials(_ credentials: [Credentials]) { + let existsJids = clients.map { $0.credentials.bareJid } + let forAdd = credentials.filter { !existsJids.contains($0.bareJid) } + let forRemove = existsJids.filter { !credentials.map { $0.bareJid }.contains($0) } + + var newClients = clients.filter { !forRemove.contains($0.credentials.bareJid) } + newClients.append(contentsOf: forAdd.map { Client(credentials: $0) }) + clients = newClients + } +} diff --git a/ConversationsClassic/AppData/Stores/NavigationStore.swift b/ConversationsClassic/AppData/Stores/NavigationStore.swift new file mode 100644 index 0000000..f5bfd2f --- /dev/null +++ b/ConversationsClassic/AppData/Stores/NavigationStore.swift @@ -0,0 +1,25 @@ +import Combine +import Foundation + +@MainActor +final class NavigationStore: ObservableObject { + enum Flow: Equatable { + enum Entering { + case welcome + case login + case registration + } + + enum Main { + case contacts + case conversations + case settings + } + + case start + case entering(Entering) + case main(Main) + } + + @Published var flow: Flow = .start +} diff --git a/ConversationsClassic/AppData/Stores/RostersStore.swift b/ConversationsClassic/AppData/Stores/RostersStore.swift new file mode 100644 index 0000000..5cdcd80 --- /dev/null +++ b/ConversationsClassic/AppData/Stores/RostersStore.swift @@ -0,0 +1,21 @@ +import Combine +import Foundation +import GRDB + +@MainActor +final class RostersStore: ObservableObject { + @Published private(set) var rosters: [Roster] = [] + + init() { + // Task { + // let observation = ValueObservation.tracking(Roster.fetchAll) + // do { + // for try await credentials in observation.values(in: Database.shared.dbQueue) { + // processCredentials(credentials) + // ready = true + // print("Fetched \(credentials.count) credentials") + // } + // } catch {} + // } + } +} diff --git a/ConversationsClassic/ConversationsClassicApp.swift b/ConversationsClassic/ConversationsClassicApp.swift index eff8cbd..75e2977 100644 --- a/ConversationsClassic/ConversationsClassicApp.swift +++ b/ConversationsClassic/ConversationsClassicApp.swift @@ -1,31 +1,17 @@ import Combine import SwiftUI -let appState = AppState() -let store = AppStore( - initialState: appState, - reducer: AppState.reducer, - middlewares: [ - loggerMiddleware(), - StartMiddleware.shared.middleware, - DatabaseMiddleware.shared.middleware, - AccountsMiddleware.shared.middleware, - XMPPMiddleware.shared.middleware, - RostersMiddleware.shared.middleware, - ChatsMiddleware.shared.middleware, - ArchivedMessagesMiddleware.shared.middleware, - ConversationMiddleware.shared.middleware, - SharingMiddleware.shared.middleware, - FileMiddleware.shared.middleware - ] -) - @main +@MainActor struct ConversationsClassic: App { + private var clientsStore = ClientsStore() + private var navigationStore = NavigationStore() + var body: some Scene { WindowGroup { - BaseNavigationView() - .environmentObject(store) + AppRootView() + .environmentObject(navigationStore) + .environmentObject(clientsStore) } } } diff --git a/ConversationsClassic/Helpers/String+Extensions.swift b/ConversationsClassic/Helpers/String+Extensions.swift index 1bbdc25..4d0bad9 100644 --- a/ConversationsClassic/Helpers/String+Extensions.swift +++ b/ConversationsClassic/Helpers/String+Extensions.swift @@ -36,28 +36,28 @@ extension String { } } -extension String { - var attachmentType: MessageAttachmentType { - let ext = (self as NSString).pathExtension.lowercased() - - switch ext { - case "mov", "mp4", "avi": - return .movie - - case "jpg", "png", "gif": - return .image - - case "mp3", "wav", "m4a": - return .audio - - case "txt", "doc", "pdf": - return .file - - default: - return .file - } - } -} +// extension String { +// var attachmentType: MessageAttachmentType { +// let ext = (self as NSString).pathExtension.lowercased() +// +// switch ext { +// case "mov", "mp4", "avi": +// return .movie +// +// case "jpg", "png", "gif": +// return .image +// +// case "mp3", "wav", "m4a": +// return .audio +// +// case "txt", "doc", "pdf": +// return .file +// +// default: +// return .file +// } +// } +// } extension String { var firstLetterColor: Color { diff --git a/ConversationsClassic/Resources/Strings/Localizable.strings b/ConversationsClassic/Resources/Strings/Localizable.strings index 8458afc..99cc122 100644 --- a/ConversationsClassic/Resources/Strings/Localizable.strings +++ b/ConversationsClassic/Resources/Strings/Localizable.strings @@ -5,21 +5,39 @@ "Global.cancel" = "Cancel"; "Global.save" = "Save"; "Global.Error.title" = "Error"; -"Global.Error.genericText" = "Something went wrong"; -"Global.Error.genericDbError" = "Database error"; -// MARK: Onboar screen +// MARK: Welcome screen "Start.subtitle" = "Free and secure messaging and calls between any existed messengers"; "Start.Btn.login" = "Enter with JID"; "Start.Btn.register" = "New Account"; + +// MARK: Login "Login.title" = "Let\'s go!"; "Login.subtitle" = "Enter your JID, it should looks like email address"; "Login.Hint.jid" = "user@domain.im"; "Login.Hint.password" = "password"; "Login.btn" = "Continue"; -"Login.Error.wrongPassword" = "Wrong password or JID"; -"Login.Error.noServer" = "Server not exists"; -"Login.Error.serverError" = "Server error. Check internet connection"; +"Login.error" = "Check internet connection, and make sure that JID and password are correct"; + + + + + + + + + + + +// MARK: Onboar screen +//"Login.title" = "Let\'s go!"; +//"Login.subtitle" = "Enter your JID, it should looks like email address"; +//"Login.Hint.jid" = "user@domain.im"; +//"Login.Hint.password" = "password"; +//"Login.btn" = "Continue"; +//"Login.Error.wrongPassword" = "Wrong password or JID"; +//"Login.Error.noServer" = "Server not exists"; +//"Login.Error.serverError" = "Server error. Check internet connection"; // MARK: Contacts screen "Contacts.title" = "Contacts"; diff --git a/ConversationsClassic/View/UIToolkit/Binding+Extensions.swift b/ConversationsClassic/UIToolkit/Binding+Extensions.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/Binding+Extensions.swift rename to ConversationsClassic/UIToolkit/Binding+Extensions.swift diff --git a/ConversationsClassic/View/UIToolkit/ButtonStyles.swift b/ConversationsClassic/UIToolkit/ButtonStyles.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/ButtonStyles.swift rename to ConversationsClassic/UIToolkit/ButtonStyles.swift diff --git a/ConversationsClassic/View/UIToolkit/Colors+Tappable.swift b/ConversationsClassic/UIToolkit/Colors+Tappable.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/Colors+Tappable.swift rename to ConversationsClassic/UIToolkit/Colors+Tappable.swift diff --git a/ConversationsClassic/View/UIToolkit/EdgeInsets+Extensions.swift b/ConversationsClassic/UIToolkit/EdgeInsets+Extensions.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/EdgeInsets+Extensions.swift rename to ConversationsClassic/UIToolkit/EdgeInsets+Extensions.swift diff --git a/ConversationsClassic/View/UIToolkit/Typography.swift b/ConversationsClassic/UIToolkit/Typography.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/Typography.swift rename to ConversationsClassic/UIToolkit/Typography.swift diff --git a/ConversationsClassic/View/UIToolkit/Vibration.swift b/ConversationsClassic/UIToolkit/Vibration.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/Vibration.swift rename to ConversationsClassic/UIToolkit/Vibration.swift diff --git a/ConversationsClassic/View/UIToolkit/View+Debug.swift b/ConversationsClassic/UIToolkit/View+Debug.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/View+Debug.swift rename to ConversationsClassic/UIToolkit/View+Debug.swift diff --git a/ConversationsClassic/View/UIToolkit/View+If.swift b/ConversationsClassic/UIToolkit/View+If.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/View+If.swift rename to ConversationsClassic/UIToolkit/View+If.swift diff --git a/ConversationsClassic/UIToolkit/View+Loader.swift b/ConversationsClassic/UIToolkit/View+Loader.swift new file mode 100644 index 0000000..37f910c --- /dev/null +++ b/ConversationsClassic/UIToolkit/View+Loader.swift @@ -0,0 +1,36 @@ +import Foundation +import SwiftUI + +public extension View { + func loadingOverlay() -> some View { + modifier(LoadingOverlay()) + } +} + +struct LoadingOverlay: ViewModifier { + func body(content: Content) -> some View { + ZStack { + content + loadingView + } + } + + private var loadingView: some View { + GeometryReader { proxyReader in + ZStack { + Color.Material.Elements.active.opacity(0.3) + .frame(maxWidth: .infinity, maxHeight: .infinity) + + // loader + ProgressView() + .progressViewStyle( + CircularProgressViewStyle(tint: .Material.Elements.active) + ) + .position(x: proxyReader.size.width / 2, y: proxyReader.size.height / 2) + .controlSize(.large) + } + } + .ignoresSafeArea() + .transition(AnyTransition.opacity.animation(.easeInOut(duration: 0.1))) + } +} diff --git a/ConversationsClassic/View/UIToolkit/View+OnLoad.swift b/ConversationsClassic/UIToolkit/View+OnLoad.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/View+OnLoad.swift rename to ConversationsClassic/UIToolkit/View+OnLoad.swift diff --git a/ConversationsClassic/View/UIToolkit/View+TappableArea.swift b/ConversationsClassic/UIToolkit/View+TappableArea.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/View+TappableArea.swift rename to ConversationsClassic/UIToolkit/View+TappableArea.swift diff --git a/ConversationsClassic/View/AppRootView.swift b/ConversationsClassic/View/AppRootView.swift new file mode 100644 index 0000000..808d238 --- /dev/null +++ b/ConversationsClassic/View/AppRootView.swift @@ -0,0 +1,38 @@ +import SwiftUI + +struct AppRootView: View { + @EnvironmentObject var navigation: NavigationStore + + var body: some View { + Group { + switch navigation.flow { + case .start: + StartScreen() + + case .entering(let entering): + switch entering { + case .welcome: + WelcomeScreen() + + case .login: + LoginScreen() + + case .registration: + RegistrationScreen() + } + + case .main(let main): + switch main { + case .contacts: + ContactsScreen() + + case .conversations: + EmptyView() + + case .settings: + EmptyView() + } + } + } + } +} diff --git a/ConversationsClassic/View/Contacts/ContactsScreen.swift b/ConversationsClassic/View/Contacts/ContactsScreen.swift new file mode 100644 index 0000000..f730823 --- /dev/null +++ b/ConversationsClassic/View/Contacts/ContactsScreen.swift @@ -0,0 +1,172 @@ +import SwiftUI + +struct ContactsScreen: View { + @EnvironmentObject var clientsStore: ClientsStore + // @State private var addPanelPresented = false + // @State private var isErrorAlertPresented = false + // @State private var errorAlertMessage = "" + // @State private var isShowingLoader = false + + @State private var rosters: [Roster] = [] + + var body: some View { + ZStack { + // Background color + Color.Material.Background.light + .ignoresSafeArea() + + // Content + VStack(spacing: 0) { + // Header + SharedNavigationBar( + centerText: .init(text: L10n.Contacts.title), + rightButton: .init( + image: Image(systemName: "plus"), + action: { + // addPanelPresented = true + } + ) + ) + + // Contacts list + if !rosters.isEmpty { + List { + ForEach(rosters) { roster in + ContactsScreenRow( + roster: roster + // isErrorAlertPresented: $isErrorAlertPresented, + // errorAlertMessage: $errorAlertMessage, + // isShowingLoader: $isShowingLoader + ) + } + } + .listStyle(.plain) + .background(Color.Material.Background.light) + } else { + Spacer() + } + + // Tab bar + SharedTabBar() + } + } + .task { + await fetchRosters() + } + // .loadingIndicator(isShowingLoader) + // .fullScreenCover(isPresented: $addPanelPresented) { + // AddContactOrChannelScreen(isPresented: $addPanelPresented) + // } + // .alert(isPresented: $isErrorAlertPresented) { + // Alert( + // title: Text(L10n.Global.Error.title), + // message: Text(errorAlertMessage), + // dismissButton: .default(Text(L10n.Global.ok)) + // ) + // } + } + + private func fetchRosters() async { + let jids = clientsStore.clients + .filter { $0.state != .disabled } + .map { $0.credentials.bareJid } + + do { + try await withThrowingTaskGroup(of: [Roster].self) { group in + for jid in jids { + group.addTask { + try await Roster.fetchAll(for: jid) + } + } + + var allRosters: [Roster] = [] + for try await rosters in group { + allRosters.append(contentsOf: rosters) + } + self.rosters = allRosters.sorted { $0.contactBareJid < $1.contactBareJid } + } + } catch {} + } +} + +private struct ContactsScreenRow: View { + var roster: Roster + // @State private var isShowingMenu = false + // @State private var isDeleteAlertPresented = false + // + // @Binding var isErrorAlertPresented: Bool + // @Binding var errorAlertMessage: String + // @Binding var isShowingLoader: Bool + + var body: some View { + SharedListRow( + iconType: .charCircle(roster.name?.firstLetter ?? roster.contactBareJid.firstLetter), + text: roster.contactBareJid + ) + // .onTapGesture { + // store.dispatch(.chatsAction(.startChat(accountJid: roster.bareJid, participantJid: roster.contactBareJid))) + // } + // .onLongPressGesture { + // isShowingMenu.toggle() + // } + // .swipeActions(edge: .trailing, allowsFullSwipe: false) { + // Button { + // isDeleteAlertPresented = true + // } label: { + // Label(L10n.Contacts.sendMessage, systemImage: "trash") + // } + // .tint(Color.red) + // } + // .contextMenu { + // Button(L10n.Contacts.sendMessage, systemImage: "message") { + // store.dispatch(.chatsAction(.startChat(accountJid: roster.bareJid, participantJid: roster.contactBareJid))) + // } + // Divider() + // + // Button(L10n.Contacts.editContact) { + // print("Edit contact") + // } + // + // Button(L10n.Contacts.selectContact) { + // print("Select contact") + // } + // + // Divider() + // Button(L10n.Contacts.deleteContact, systemImage: "trash", role: .destructive) { + // isDeleteAlertPresented = true + // } + // } + // .actionSheet(isPresented: $isDeleteAlertPresented) { + // ActionSheet( + // title: Text(L10n.Contacts.Delete.title), + // message: Text(L10n.Contacts.Delete.message), + // buttons: [ + // .destructive(Text(L10n.Contacts.Delete.deleteFromDevice)) { + // store.dispatch(.rostersAction(.markRosterAsLocallyDeleted(ownerJID: roster.bareJid, contactJID: roster.contactBareJid))) + // }, + // .destructive(Text(L10n.Contacts.Delete.deleteCompletely)) { + // isShowingLoader = true + // store.dispatch(.rostersAction(.deleteRoster(ownerJID: roster.bareJid, contactJID: roster.contactBareJid))) + // }, + // .cancel(Text(L10n.Global.cancel)) + // ] + // ) + // } + // .onChange(of: store.state.rostersState.rosters) { _ in + // endOfDeleting() + // } + // .onChange(of: store.state.rostersState.deleteRosterError) { _ in + // endOfDeleting() + // } + } + + // private func endOfDeleting() { + // if isShowingLoader { + // isShowingLoader = false + // if let error = store.state.rostersState.deleteRosterError { + // errorAlertMessage = error + // isErrorAlertPresented = true + // } + // } + // } +} diff --git a/ConversationsClassic/View/Entering/LoginScreen.swift b/ConversationsClassic/View/Entering/LoginScreen.swift new file mode 100644 index 0000000..b7aa509 --- /dev/null +++ b/ConversationsClassic/View/Entering/LoginScreen.swift @@ -0,0 +1,141 @@ +import Combine +import Martin +import SwiftUI + +struct LoginScreen: View { + @EnvironmentObject var navigation: NavigationStore + @EnvironmentObject var clientsStore: ClientsStore + + enum Field { + case userJid + case password + } + + @FocusState private var focus: Field? + + @State private var isLoading = false + @State private var isError = false + + #if DEBUG + @State private var jidStr: String = "nartest1@conversations.im" + @State private var pass: String = "nartest12345" + // @State private var jidStr: String = "test1@test.anal.company" + // @State private var pass: String = "12345" + #else + @State private var jidStr: String = "" + @State private var pass: String = "" + #endif + + public var body: some View { + ZStack { + // background + Color.Material.Background.light + .ignoresSafeArea() + + // content + VStack(spacing: 32) { + // icon + Image.logo + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 120, height: 120) + + // texts + VStack(spacing: 10) { + Text(L10n.Login.title) + .font(.head1l) + .foregroundColor(.Material.Text.main) + .fixedSize(horizontal: true, vertical: false) + Text(L10n.Login.subtitle) + .font(.body2) + .foregroundColor(.Material.Text.sub) + .multilineTextAlignment(.center) + .fixedSize(horizontal: false, vertical: true) + } + + VStack(spacing: 16) { + UniversalInputCollection.TextField( + prompt: L10n.Login.Hint.jid, + text: $jidStr, + focus: $focus, + fieldType: .userJid, + contentType: .emailAddress, + keyboardType: .emailAddress, + submitLabel: .next, + action: { + focus = .password + } + ) + UniversalInputCollection.SecureField( + prompt: L10n.Login.Hint.password, + text: $pass, + focus: $focus, + fieldType: .password, + submitLabel: .go, + action: { + focus = nil + } + ) + + Button { + Task { + await tryLogin() + } + } label: { + Text(L10n.Login.btn) + } + .buttonStyle(PrimaryButtonStyle()) + .disabled(!loginInputValid) + + Button { + withAnimation { + navigation.flow = .entering(.welcome) + } + } label: { + Text("\(Image(systemName: "chevron.left")) \(L10n.Global.back)") + .foregroundColor(.Material.Elements.active) + .font(.body2) + } + } + } + .padding(.horizontal, 32) + } + .if(isLoading) { + $0.loadingOverlay() + } + .alert(isPresented: $isError) { + Alert( + title: Text(L10n.Global.Error.title), + message: Text(L10n.Login.error), + dismissButton: .default(Text(L10n.Global.ok)) + ) + } + } + + private var loginInputValid: Bool { + !jidStr.isEmpty && !pass.isEmpty && UniversalInputCollection.Validators.isEmail(jidStr) + } + + private func tryLogin() async { + isLoading = true + + // login with fake timeout + async let sleep: Void? = try? await Task.sleep(nanoseconds: 1 * NSEC_PER_SEC) + async let request = await Client.tryLogin(with: .init(bareJid: jidStr, pass: pass, isActive: true)) + let result = await(request, sleep).0 + + switch result { + case .success(let client): + clientsStore.addNewClient(client) + isLoading = false + isError = false + if navigation.flow == .entering(.login) { + navigation.flow = .main(.contacts) + } + + case .failure: + isLoading = false + isError = true + } + } +} diff --git a/ConversationsClassic/View/Entering/RegistrationScreen.swift b/ConversationsClassic/View/Entering/RegistrationScreen.swift new file mode 100644 index 0000000..b2366af --- /dev/null +++ b/ConversationsClassic/View/Entering/RegistrationScreen.swift @@ -0,0 +1,22 @@ +import SwiftUI + +struct RegistrationScreen: View { + @EnvironmentObject var navigation: NavigationStore + + public var body: some View { + ZStack { + Color.Material.Background.light + Button { + withAnimation { + navigation.flow = .entering(.welcome) + } + } label: { + VStack { + Text("Not yet implemented") + Text(L10n.Global.back) + } + } + } + .ignoresSafeArea() + } +} diff --git a/ConversationsClassic/View/Entering/WelcomeScreen.swift b/ConversationsClassic/View/Entering/WelcomeScreen.swift new file mode 100644 index 0000000..404d102 --- /dev/null +++ b/ConversationsClassic/View/Entering/WelcomeScreen.swift @@ -0,0 +1,56 @@ +import SwiftUI + +struct WelcomeScreen: View { + @EnvironmentObject var navigation: NavigationStore + + public var body: some View { + ZStack { + // background + Color.Material.Background.light + .ignoresSafeArea() + + // content + VStack(spacing: 32) { + // icon + Image.logo + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 120, height: 120) + + // texts + VStack(spacing: 10) { + Text(L10n.Global.name) + .font(.head1r) + .foregroundColor(.Material.Text.main) + .fixedSize(horizontal: true, vertical: false) + Text(L10n.Start.subtitle) + .font(.body2) + .foregroundColor(.Material.Text.sub) + .fixedSize(horizontal: false, vertical: true) + .multilineTextAlignment(.center) + } + + // buttons + VStack(spacing: 16) { + Button { + withAnimation { + navigation.flow = .entering(.login) + } + } label: { + Text(L10n.Start.Btn.login) + } + .buttonStyle(SecondaryButtonStyle()) + Button { + withAnimation { + navigation.flow = .entering(.registration) + } + } label: { + Text(L10n.Start.Btn.register) + } + .buttonStyle(PrimaryButtonStyle()) + } + } + .padding(.horizontal, 32) + } + } +} diff --git a/ConversationsClassic/View/SharedComponents/SharedTabBar.swift b/ConversationsClassic/View/SharedComponents/SharedTabBar.swift index 8ca982c..f8620ec 100644 --- a/ConversationsClassic/View/SharedComponents/SharedTabBar.swift +++ b/ConversationsClassic/View/SharedComponents/SharedTabBar.swift @@ -8,9 +8,9 @@ struct SharedTabBar: View { .frame(height: 0.2) .foregroundColor(.Material.Shape.separator) HStack(spacing: 0) { - SharedTabBarButton(buttonFlow: .contacts) - SharedTabBarButton(buttonFlow: .chats) - SharedTabBarButton(buttonFlow: .settings) + SharedTabBarButton(buttonFlow: .main(.contacts)) + SharedTabBarButton(buttonFlow: .main(.conversations)) + SharedTabBarButton(buttonFlow: .main(.settings)) } .background(Color.Material.Background.dark) } @@ -19,38 +19,40 @@ struct SharedTabBar: View { } private struct SharedTabBarButton: View { - @EnvironmentObject var store: AppStore + @EnvironmentObject var navigation: NavigationStore - let buttonFlow: AppFlow + let buttonFlow: NavigationStore.Flow var body: some View { ZStack { VStack(spacing: 2) { buttonImg - .foregroundColor(buttonFlow == store.state.currentFlow ? .Material.Elements.active : .Material.Elements.inactive) + .foregroundColor(buttonFlow == navigation.flow ? .Material.Elements.active : .Material.Elements.inactive) .font(.system(size: 24, weight: .light)) .symbolRenderingMode(.hierarchical) Text(buttonTitle) .font(.sub1) - .foregroundColor(buttonFlow == store.state.currentFlow ? .Material.Text.main : .Material.Elements.inactive) + .foregroundColor(buttonFlow == navigation.flow ? .Material.Text.main : .Material.Elements.inactive) } Rectangle() .foregroundColor(.white.opacity(0.01)) .onTapGesture { - store.dispatch(.changeFlow(buttonFlow)) + withAnimation { + navigation.flow = buttonFlow + } } } } var buttonImg: Image { switch buttonFlow { - case .contacts: + case .main(.contacts): return Image(systemName: "person.2.fill") - case .chats: + case .main(.conversations): return Image(systemName: "bubble.left.fill") - case .settings: + case .main(.settings): return Image(systemName: "gearshape.fill") default: @@ -60,13 +62,13 @@ private struct SharedTabBarButton: View { var buttonTitle: String { switch buttonFlow { - case .contacts: + case .main(.contacts): return "Contacts" - case .chats: + case .main(.conversations): return "Chats" - case .settings: + case .main(.settings): return "Settings" default: diff --git a/ConversationsClassic/View/StartScreen.swift b/ConversationsClassic/View/StartScreen.swift new file mode 100644 index 0000000..0999ebd --- /dev/null +++ b/ConversationsClassic/View/StartScreen.swift @@ -0,0 +1,28 @@ +import SwiftUI + +struct StartScreen: View { + @EnvironmentObject var clientsStore: ClientsStore + @EnvironmentObject var navigation: NavigationStore + + var body: some View { + ZStack { + Color.Material.Background.light + Image.logo + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 200, height: 200) + } + .ignoresSafeArea() + .onAppear { + clientsStore.startFetching() + } + .onChange(of: clientsStore.ready) { ready in + if ready { + let flow: NavigationStore.Flow = clientsStore.clients.isEmpty ? .entering(.welcome) : .main(.conversations) + withAnimation { + navigation.flow = flow + } + } + } + } +} diff --git a/ConversationsClassic/AppCore/Actions/AccountsActions.swift b/old/AppCore/Actions/AccountsActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/AccountsActions.swift rename to old/AppCore/Actions/AccountsActions.swift diff --git a/ConversationsClassic/AppCore/Actions/AppActions.swift b/old/AppCore/Actions/AppActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/AppActions.swift rename to old/AppCore/Actions/AppActions.swift diff --git a/ConversationsClassic/AppCore/Actions/ChatsActions.swift b/old/AppCore/Actions/ChatsActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/ChatsActions.swift rename to old/AppCore/Actions/ChatsActions.swift diff --git a/ConversationsClassic/AppCore/Actions/ConversationActions.swift b/old/AppCore/Actions/ConversationActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/ConversationActions.swift rename to old/AppCore/Actions/ConversationActions.swift diff --git a/ConversationsClassic/AppCore/Actions/DatabaseActions.swift b/old/AppCore/Actions/DatabaseActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/DatabaseActions.swift rename to old/AppCore/Actions/DatabaseActions.swift diff --git a/ConversationsClassic/AppCore/Actions/FileActions.swift b/old/AppCore/Actions/FileActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/FileActions.swift rename to old/AppCore/Actions/FileActions.swift diff --git a/ConversationsClassic/AppCore/Actions/RostersActions.swift b/old/AppCore/Actions/RostersActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/RostersActions.swift rename to old/AppCore/Actions/RostersActions.swift diff --git a/ConversationsClassic/AppCore/Actions/SharingActions.swift b/old/AppCore/Actions/SharingActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/SharingActions.swift rename to old/AppCore/Actions/SharingActions.swift diff --git a/ConversationsClassic/AppCore/Actions/StartActions.swift b/old/AppCore/Actions/StartActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/StartActions.swift rename to old/AppCore/Actions/StartActions.swift diff --git a/ConversationsClassic/AppCore/Actions/XMPPActions.swift b/old/AppCore/Actions/XMPPActions.swift similarity index 100% rename from ConversationsClassic/AppCore/Actions/XMPPActions.swift rename to old/AppCore/Actions/XMPPActions.swift diff --git a/ConversationsClassic/AppCore/AppStore.swift b/old/AppCore/AppStore.swift similarity index 100% rename from ConversationsClassic/AppCore/AppStore.swift rename to old/AppCore/AppStore.swift diff --git a/ConversationsClassic/AppCore/Database/Database+Martin/Database+Martin.swift b/old/AppCore/Database/Database+Martin/Database+Martin.swift similarity index 100% rename from ConversationsClassic/AppCore/Database/Database+Martin/Database+Martin.swift rename to old/AppCore/Database/Database+Martin/Database+Martin.swift diff --git a/ConversationsClassic/AppCore/Database/Database+Martin/Database+MartinChannelManager.swift b/old/AppCore/Database/Database+Martin/Database+MartinChannelManager.swift similarity index 100% rename from ConversationsClassic/AppCore/Database/Database+Martin/Database+MartinChannelManager.swift rename to old/AppCore/Database/Database+Martin/Database+MartinChannelManager.swift diff --git a/ConversationsClassic/AppCore/Database/Database+Martin/Database+MartinChatManager.swift b/old/AppCore/Database/Database+Martin/Database+MartinChatManager.swift similarity index 100% rename from ConversationsClassic/AppCore/Database/Database+Martin/Database+MartinChatManager.swift rename to old/AppCore/Database/Database+Martin/Database+MartinChatManager.swift diff --git a/ConversationsClassic/AppCore/Database/Database+Martin/Database+MartinRoomManager.swift b/old/AppCore/Database/Database+Martin/Database+MartinRoomManager.swift similarity index 100% rename from ConversationsClassic/AppCore/Database/Database+Martin/Database+MartinRoomManager.swift rename to old/AppCore/Database/Database+Martin/Database+MartinRoomManager.swift diff --git a/ConversationsClassic/AppCore/Database/Database+Martin/Database+MartinRosterManager.swift b/old/AppCore/Database/Database+Martin/Database+MartinRosterManager.swift similarity index 100% rename from ConversationsClassic/AppCore/Database/Database+Martin/Database+MartinRosterManager.swift rename to old/AppCore/Database/Database+Martin/Database+MartinRosterManager.swift diff --git a/ConversationsClassic/AppCore/Database/Database+Migrations.swift b/old/AppCore/Database/Database+Migrations.swift similarity index 100% rename from ConversationsClassic/AppCore/Database/Database+Migrations.swift rename to old/AppCore/Database/Database+Migrations.swift diff --git a/ConversationsClassic/AppCore/Database/Database.swift b/old/AppCore/Database/Database.swift similarity index 100% rename from ConversationsClassic/AppCore/Database/Database.swift rename to old/AppCore/Database/Database.swift diff --git a/ConversationsClassic/AppCore/Files/DownloadManager.swift b/old/AppCore/Files/DownloadManager.swift similarity index 100% rename from ConversationsClassic/AppCore/Files/DownloadManager.swift rename to old/AppCore/Files/DownloadManager.swift diff --git a/ConversationsClassic/AppCore/Files/FileProcessing.swift b/old/AppCore/Files/FileProcessing.swift similarity index 100% rename from ConversationsClassic/AppCore/Files/FileProcessing.swift rename to old/AppCore/Files/FileProcessing.swift diff --git a/ConversationsClassic/AppCore/Middlewares/AccountsMiddleware.swift b/old/AppCore/Middlewares/AccountsMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/AccountsMiddleware.swift rename to old/AppCore/Middlewares/AccountsMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/ArchivedMessagesMiddleware.swift b/old/AppCore/Middlewares/ArchivedMessagesMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/ArchivedMessagesMiddleware.swift rename to old/AppCore/Middlewares/ArchivedMessagesMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/ChatsMiddleware.swift b/old/AppCore/Middlewares/ChatsMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/ChatsMiddleware.swift rename to old/AppCore/Middlewares/ChatsMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/ConversationMiddleware.swift b/old/AppCore/Middlewares/ConversationMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/ConversationMiddleware.swift rename to old/AppCore/Middlewares/ConversationMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/DatabaseMiddleware.swift b/old/AppCore/Middlewares/DatabaseMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/DatabaseMiddleware.swift rename to old/AppCore/Middlewares/DatabaseMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/FileMiddleware.swift b/old/AppCore/Middlewares/FileMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/FileMiddleware.swift rename to old/AppCore/Middlewares/FileMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/LoggerMiddleware.swift b/old/AppCore/Middlewares/LoggerMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/LoggerMiddleware.swift rename to old/AppCore/Middlewares/LoggerMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/RostersMiddleware.swift b/old/AppCore/Middlewares/RostersMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/RostersMiddleware.swift rename to old/AppCore/Middlewares/RostersMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/SharingMiddleware.swift b/old/AppCore/Middlewares/SharingMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/SharingMiddleware.swift rename to old/AppCore/Middlewares/SharingMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/StartMiddleware.swift b/old/AppCore/Middlewares/StartMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/StartMiddleware.swift rename to old/AppCore/Middlewares/StartMiddleware.swift diff --git a/ConversationsClassic/AppCore/Middlewares/XMPPMiddleware.swift b/old/AppCore/Middlewares/XMPPMiddleware.swift similarity index 100% rename from ConversationsClassic/AppCore/Middlewares/XMPPMiddleware.swift rename to old/AppCore/Middlewares/XMPPMiddleware.swift diff --git a/ConversationsClassic/AppCore/Models/Account.swift b/old/AppCore/Models/Account.swift similarity index 100% rename from ConversationsClassic/AppCore/Models/Account.swift rename to old/AppCore/Models/Account.swift diff --git a/ConversationsClassic/AppCore/Models/Channel.swift b/old/AppCore/Models/Channel.swift similarity index 100% rename from ConversationsClassic/AppCore/Models/Channel.swift rename to old/AppCore/Models/Channel.swift diff --git a/ConversationsClassic/AppCore/Models/Chat.swift b/old/AppCore/Models/Chat.swift similarity index 100% rename from ConversationsClassic/AppCore/Models/Chat.swift rename to old/AppCore/Models/Chat.swift diff --git a/ConversationsClassic/AppCore/Models/ConnectionStatus.swift b/old/AppCore/Models/ConnectionStatus.swift similarity index 100% rename from ConversationsClassic/AppCore/Models/ConnectionStatus.swift rename to old/AppCore/Models/ConnectionStatus.swift diff --git a/ConversationsClassic/AppCore/Models/Message.swift b/old/AppCore/Models/Message.swift similarity index 100% rename from ConversationsClassic/AppCore/Models/Message.swift rename to old/AppCore/Models/Message.swift diff --git a/ConversationsClassic/AppCore/Models/Room.swift b/old/AppCore/Models/Room.swift similarity index 100% rename from ConversationsClassic/AppCore/Models/Room.swift rename to old/AppCore/Models/Room.swift diff --git a/ConversationsClassic/AppCore/Models/Roster.swift b/old/AppCore/Models/Roster.swift similarity index 100% rename from ConversationsClassic/AppCore/Models/Roster.swift rename to old/AppCore/Models/Roster.swift diff --git a/ConversationsClassic/AppCore/Models/ServerFeature.swift b/old/AppCore/Models/ServerFeature.swift similarity index 100% rename from ConversationsClassic/AppCore/Models/ServerFeature.swift rename to old/AppCore/Models/ServerFeature.swift diff --git a/ConversationsClassic/AppCore/Reducers/AccountsReducer.swift b/old/AppCore/Reducers/AccountsReducer.swift similarity index 100% rename from ConversationsClassic/AppCore/Reducers/AccountsReducer.swift rename to old/AppCore/Reducers/AccountsReducer.swift diff --git a/ConversationsClassic/AppCore/Reducers/AppReducer.swift b/old/AppCore/Reducers/AppReducer.swift similarity index 100% rename from ConversationsClassic/AppCore/Reducers/AppReducer.swift rename to old/AppCore/Reducers/AppReducer.swift diff --git a/ConversationsClassic/AppCore/Reducers/ChatsReducer.swift b/old/AppCore/Reducers/ChatsReducer.swift similarity index 100% rename from ConversationsClassic/AppCore/Reducers/ChatsReducer.swift rename to old/AppCore/Reducers/ChatsReducer.swift diff --git a/ConversationsClassic/AppCore/Reducers/ConversationReducer.swift b/old/AppCore/Reducers/ConversationReducer.swift similarity index 100% rename from ConversationsClassic/AppCore/Reducers/ConversationReducer.swift rename to old/AppCore/Reducers/ConversationReducer.swift diff --git a/ConversationsClassic/AppCore/Reducers/RostersReducer.swift b/old/AppCore/Reducers/RostersReducer.swift similarity index 100% rename from ConversationsClassic/AppCore/Reducers/RostersReducer.swift rename to old/AppCore/Reducers/RostersReducer.swift diff --git a/ConversationsClassic/AppCore/Reducers/SharingReducer.swift b/old/AppCore/Reducers/SharingReducer.swift similarity index 100% rename from ConversationsClassic/AppCore/Reducers/SharingReducer.swift rename to old/AppCore/Reducers/SharingReducer.swift diff --git a/ConversationsClassic/AppCore/Reducers/StartReducer.swift b/old/AppCore/Reducers/StartReducer.swift similarity index 100% rename from ConversationsClassic/AppCore/Reducers/StartReducer.swift rename to old/AppCore/Reducers/StartReducer.swift diff --git a/ConversationsClassic/AppCore/State/AccountsState.swift b/old/AppCore/State/AccountsState.swift similarity index 100% rename from ConversationsClassic/AppCore/State/AccountsState.swift rename to old/AppCore/State/AccountsState.swift diff --git a/ConversationsClassic/AppCore/State/AppState.swift b/old/AppCore/State/AppState.swift similarity index 100% rename from ConversationsClassic/AppCore/State/AppState.swift rename to old/AppCore/State/AppState.swift diff --git a/ConversationsClassic/AppCore/State/ChatsState.swift b/old/AppCore/State/ChatsState.swift similarity index 100% rename from ConversationsClassic/AppCore/State/ChatsState.swift rename to old/AppCore/State/ChatsState.swift diff --git a/ConversationsClassic/AppCore/State/ConversationState.swift b/old/AppCore/State/ConversationState.swift similarity index 100% rename from ConversationsClassic/AppCore/State/ConversationState.swift rename to old/AppCore/State/ConversationState.swift diff --git a/ConversationsClassic/AppCore/State/RostersState.swift b/old/AppCore/State/RostersState.swift similarity index 100% rename from ConversationsClassic/AppCore/State/RostersState.swift rename to old/AppCore/State/RostersState.swift diff --git a/ConversationsClassic/AppCore/State/SharingState.swift b/old/AppCore/State/SharingState.swift similarity index 100% rename from ConversationsClassic/AppCore/State/SharingState.swift rename to old/AppCore/State/SharingState.swift diff --git a/ConversationsClassic/AppCore/State/StartState.swift b/old/AppCore/State/StartState.swift similarity index 100% rename from ConversationsClassic/AppCore/State/StartState.swift rename to old/AppCore/State/StartState.swift diff --git a/ConversationsClassic/AppCore/XMPP/XMPPService.swift b/old/AppCore/XMPP/XMPPService.swift similarity index 100% rename from ConversationsClassic/AppCore/XMPP/XMPPService.swift rename to old/AppCore/XMPP/XMPPService.swift diff --git a/old/Generated/.gitignore b/old/Generated/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/old/Generated/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/old/Helpers/Bool+Extensions.swift b/old/Helpers/Bool+Extensions.swift new file mode 100644 index 0000000..b26674c --- /dev/null +++ b/old/Helpers/Bool+Extensions.swift @@ -0,0 +1,7 @@ +import Foundation + +extension Bool { + var intValue: Int { + self ? 1 : 0 + } +} diff --git a/old/Helpers/Const.swift b/old/Helpers/Const.swift new file mode 100644 index 0000000..c96edfd --- /dev/null +++ b/old/Helpers/Const.swift @@ -0,0 +1,53 @@ +import Foundation +import UIKit + +enum Const { + // // Network + // #if DEBUG + // static let baseUrl = "staging.some.com/api" + // #else + // static let baseUrl = "prod.some.com/api" + // #endif + // static let requestTimeout = 15.0 + // static let networkLogging = true + + // App + static var appVersion: String { + let info = Bundle.main.infoDictionary + let appVersion = info?["CFBundleShortVersionString"] as? String ?? "Unknown" + let appBuild = info?[kCFBundleVersionKey as String] as? String ?? "Unknown" + return "v \(appVersion)(\(appBuild))" + } + + static var appName: String { + Bundle.main.bundleIdentifier ?? "Conversations Classic iOS" + } + + // Trusted servers + enum TrustedServers: String { + case narayana = "narayana.im" + case conversations = "conversations.im" + } + + // Limit for video for sharing + static let videoDurationLimit = 60.0 + + // Upload/download file folder + static let fileFolder = "Downloads" + + // Grid size for gallery preview (3 in a row) + static let galleryGridSize = UIScreen.main.bounds.width / 3 + + // Size for map preview for location messages + static let mapPreviewSize = UIScreen.main.bounds.width * 0.5 + + // Size for attachment preview + static let attachmentPreviewSize = UIScreen.main.bounds.width * 0.5 + + // Lenght in days for MAM request + static let mamRequestDaysLength = 30 + + // Limits for messages pagination + static let messagesPageMin = 20 + static let messagesPageMax = 100 +} diff --git a/old/Helpers/Map+Extensions.swift b/old/Helpers/Map+Extensions.swift new file mode 100644 index 0000000..4c25921 --- /dev/null +++ b/old/Helpers/Map+Extensions.swift @@ -0,0 +1,16 @@ +import MapKit + +extension MKCoordinateRegion: Equatable { + public static func == (lhs: MKCoordinateRegion, rhs: MKCoordinateRegion) -> Bool { + lhs.center.latitude == rhs.center.latitude && + lhs.center.longitude == rhs.center.longitude && + lhs.span.latitudeDelta == rhs.span.latitudeDelta && + lhs.span.longitudeDelta == rhs.span.longitudeDelta + } +} + +extension CLLocationCoordinate2D: Identifiable { + public var id: String { + "\(latitude)-\(longitude)" + } +} diff --git a/ConversationsClassic/Helpers/Set+Extensions.swift b/old/Helpers/Set+Extensions.swift similarity index 100% rename from ConversationsClassic/Helpers/Set+Extensions.swift rename to old/Helpers/Set+Extensions.swift diff --git a/old/Helpers/String+Extensions.swift b/old/Helpers/String+Extensions.swift new file mode 100644 index 0000000..1bbdc25 --- /dev/null +++ b/old/Helpers/String+Extensions.swift @@ -0,0 +1,106 @@ +import CoreLocation +import Foundation +import SwiftUI + +extension String { + var firstLetter: String { + String(prefix(1)).uppercased() + } + + var makeReply: String { + let allLines = components(separatedBy: .newlines) + let nonBlankLines = allLines.filter { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } + var result = nonBlankLines.joined(separator: "\n") + result = "> \(result)" + return result + } + + var isLocation: Bool { + hasPrefix("geo:") + } + + var getLatLon: CLLocationCoordinate2D { + let geo = components(separatedBy: ":")[1] + let parts = geo.components(separatedBy: ",") + let lat = Double(parts[0]) ?? 0.0 + let lon = Double(parts[1]) ?? 0.0 + return CLLocationCoordinate2D(latitude: lat, longitude: lon) + } + + var isContact: Bool { + hasPrefix("contact:") + } + + var getContactJid: String { + components(separatedBy: ":")[1] + } +} + +extension String { + var attachmentType: MessageAttachmentType { + let ext = (self as NSString).pathExtension.lowercased() + + switch ext { + case "mov", "mp4", "avi": + return .movie + + case "jpg", "png", "gif": + return .image + + case "mp3", "wav", "m4a": + return .audio + + case "txt", "doc", "pdf": + return .file + + default: + return .file + } + } +} + +extension String { + var firstLetterColor: Color { + let firstLetter = self.firstLetter + switch firstLetter { + case "A", "M", "Y": + return Color.Rainbow.tortoiseLight500 + + case "B", "N", "Z": + return Color.Rainbow.orangeLight500 + + case "C", "O": + return Color.Rainbow.yellowLight500 + + case "D", "P": + return Color.Rainbow.greenLight500 + + case "E", "Q": + return Color.Rainbow.blueLight500 + + case "F", "R": + return Color.Rainbow.magentaLight500 + + case "G", "S": + return Color.Rainbow.tortoiseDark500 + + case "H", "T": + return Color.Rainbow.orangeDark500 + + case "I", "U": + return Color.Rainbow.yellowDark500 + + case "J", "V": + return Color.Rainbow.greenDark500 + + case "K", "W": + return Color.Rainbow.blueDark500 + + case "L", "X": + return Color.Rainbow.magentaDark500 + + default: + return Color.Rainbow.tortoiseLight500 + } + } +} diff --git a/old/Helpers/TimeInterval+Extensions.swift b/old/Helpers/TimeInterval+Extensions.swift new file mode 100644 index 0000000..0dde77a --- /dev/null +++ b/old/Helpers/TimeInterval+Extensions.swift @@ -0,0 +1,9 @@ +import Foundation + +extension TimeInterval { + var minAndSec: String { + let minutes = Int(self) / 60 + let seconds = Int(self) % 60 + return String(format: "%02d:%02d", minutes, seconds) + } +} diff --git a/old/Helpers/UIApplication+Extensions.swift b/old/Helpers/UIApplication+Extensions.swift new file mode 100644 index 0000000..63550f5 --- /dev/null +++ b/old/Helpers/UIApplication+Extensions.swift @@ -0,0 +1,10 @@ +import UIKit + +func openAppSettings() { + if + let appSettingsUrl = URL(string: UIApplication.openSettingsURLString), + UIApplication.shared.canOpenURL(appSettingsUrl) + { + UIApplication.shared.open(appSettingsUrl, completionHandler: nil) + } +} diff --git a/old/Helpers/URL+Extensions.swift b/old/Helpers/URL+Extensions.swift new file mode 100644 index 0000000..c84c26a --- /dev/null +++ b/old/Helpers/URL+Extensions.swift @@ -0,0 +1,13 @@ +import UniformTypeIdentifiers + +extension URL { + var mimeType: String { + let pathExtension = self.pathExtension + + if let uti = UTType(filenameExtension: pathExtension) { + return uti.preferredMIMEType ?? "application/octet-stream" + } else { + return "application/octet-stream" + } + } +} diff --git a/old/Helpers/UserDefaultsWrapper.swift b/old/Helpers/UserDefaultsWrapper.swift new file mode 100644 index 0000000..535e9e9 --- /dev/null +++ b/old/Helpers/UserDefaultsWrapper.swift @@ -0,0 +1,32 @@ +import Foundation + +// Wrapper +@propertyWrapper +struct Storage { + private let key: String + private let defaultValue: T + + init(key: String, defaultValue: T) { + self.key = key + self.defaultValue = defaultValue + } + + var wrappedValue: T { + get { + // Read value from UserDefaults + UserDefaults.standard.object(forKey: key) as? T ?? defaultValue + } + set { + // Set value to UserDefaults + UserDefaults.standard.set(newValue, forKey: key) + } + } +} + +// Storage +private let keyLocalizationSelected = "conversations.classic.user.defaults.localizationSelected" + +enum UserSettings { + @Storage(key: keyLocalizationSelected, defaultValue: false) + static var localizationSelectedByUser: Bool +} diff --git a/old/Resources/Assets/Colors.xcassets/Contents.json b/old/Resources/Assets/Colors.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/Contents.json b/old/Resources/Assets/Colors.xcassets/material/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/background/Contents.json b/old/Resources/Assets/Colors.xcassets/material/background/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/background/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/background/dark.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/background/dark.colorset/Contents.json new file mode 100644 index 0000000..bdb682b --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/background/dark.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xE4", + "green" : "0xE4", + "red" : "0xE4" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/background/light.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/background/light.colorset/Contents.json new file mode 100644 index 0000000..b8c6d9e --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/background/light.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "235", + "green" : "235", + "red" : "235" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/elements/Contents.json b/old/Resources/Assets/Colors.xcassets/material/elements/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/elements/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/elements/active.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/elements/active.colorset/Contents.json new file mode 100644 index 0000000..5a42e0f --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/elements/active.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x4D", + "green" : "0x46", + "red" : "0x3C" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/elements/inactive.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/elements/inactive.colorset/Contents.json new file mode 100644 index 0000000..944aec1 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/elements/inactive.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xAC", + "green" : "0xA3", + "red" : "0x95" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/shape/Contents.json b/old/Resources/Assets/Colors.xcassets/material/shape/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/shape/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/shape/alternate.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/shape/alternate.colorset/Contents.json new file mode 100644 index 0000000..72469b0 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/shape/alternate.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "201", + "green" : "227", + "red" : "199" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/shape/black.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/shape/black.colorset/Contents.json new file mode 100644 index 0000000..1c18f8d --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/shape/black.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x62", + "green" : "0x59", + "red" : "0x4A" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/shape/separator.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/shape/separator.colorset/Contents.json new file mode 100644 index 0000000..3d66dc2 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/shape/separator.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "189", + "green" : "189", + "red" : "189" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/shape/white.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/shape/white.colorset/Contents.json new file mode 100644 index 0000000..fafa476 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/shape/white.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/text/Contents.json b/old/Resources/Assets/Colors.xcassets/material/text/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/text/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/text/main.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/text/main.colorset/Contents.json new file mode 100644 index 0000000..dfe1a2d --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/text/main.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x36", + "green" : "0x31", + "red" : "0x2A" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/text/sub.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/text/sub.colorset/Contents.json new file mode 100644 index 0000000..4db6d18 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/text/sub.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x78", + "green" : "0x6D", + "red" : "0x5A" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/material/text/white.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/material/text/white.colorset/Contents.json new file mode 100644 index 0000000..2cedebe --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/material/text/white.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xEF", + "green" : "0xEF", + "red" : "0xEF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/Contents.json b/old/Resources/Assets/Colors.xcassets/old/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/background/Contents.json b/old/Resources/Assets/Colors.xcassets/old/background/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/background/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/primary/Contents.json b/old/Resources/Assets/Colors.xcassets/old/primary/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/primary/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/primary/c100.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/primary/c100.colorset/Contents.json new file mode 100644 index 0000000..2e838f5 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/primary/c100.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xD9", + "green" : "0xD7", + "red" : "0xD3" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/primary/c200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/primary/c200.colorset/Contents.json new file mode 100644 index 0000000..8bfa21b --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/primary/c200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xC2", + "green" : "0xBD", + "red" : "0xB5" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/primary/c400.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/primary/c400.colorset/Contents.json new file mode 100644 index 0000000..c61781a --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/primary/c400.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x9A", + "green" : "0x8F", + "red" : "0x7D" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/primary/c50.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/primary/c50.colorset/Contents.json new file mode 100644 index 0000000..a61d481 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/primary/c50.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFE" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/primary/c500main.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/primary/c500main.colorset/Contents.json new file mode 100644 index 0000000..d4b5ad5 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/primary/c500main.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x89", + "green" : "0x7C", + "red" : "0x66" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c100.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c100.colorset/Contents.json new file mode 100644 index 0000000..9d735e4 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c100.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xB4", + "green" : "0xEC", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c200.colorset/Contents.json new file mode 100644 index 0000000..aaeed90 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x83", + "green" : "0xF0", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c300.colorset/Contents.json new file mode 100644 index 0000000..a8c8ffc --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x52", + "green" : "0xD5", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c400.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c400.colorset/Contents.json new file mode 100644 index 0000000..c24864c --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c400.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x2D", + "green" : "0xCA", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c50.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c50.colorset/Contents.json new file mode 100644 index 0000000..c345981 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c50.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xE1", + "green" : "0xF8", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c500main.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c500main.colorset/Contents.json new file mode 100644 index 0000000..11f3048 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c500main.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x14", + "green" : "0xC1", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c600.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c600.colorset/Contents.json new file mode 100644 index 0000000..2589002 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c600.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x0F", + "green" : "0xB3", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c700.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c700.colorset/Contents.json new file mode 100644 index 0000000..b745fb4 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c700.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x0D", + "green" : "0xA0", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c800.colorset/Contents.json new file mode 100644 index 0000000..9024695 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x0C", + "green" : "0x8F", + "red" : "0xFE" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/secondary/c900.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/secondary/c900.colorset/Contents.json new file mode 100644 index 0000000..8b4228e --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/secondary/c900.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x0B", + "green" : "0x70", + "red" : "0xFE" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/text/Contents.json b/old/Resources/Assets/Colors.xcassets/old/text/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/text/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/text/main.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/text/main.colorset/Contents.json new file mode 100644 index 0000000..9c8eb66 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/text/main.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x2D", + "green" : "0x2D", + "red" : "0x2D" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/old/text/sub.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/old/text/sub.colorset/Contents.json new file mode 100644 index 0000000..2e42b95 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/old/text/sub.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x78", + "green" : "0x78", + "red" : "0x78" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blue200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blue200.colorset/Contents.json new file mode 100644 index 0000000..12b3b32 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blue200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.976", + "green" : "0.792", + "red" : "0.565" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blue300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blue300.colorset/Contents.json new file mode 100644 index 0000000..0b975d5 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blue300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.965", + "green" : "0.710", + "red" : "0.392" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blue500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blue500.colorset/Contents.json new file mode 100644 index 0000000..3c05e0a --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blue500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.953", + "green" : "0.588", + "red" : "0.129" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blue800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blue800.colorset/Contents.json new file mode 100644 index 0000000..865adb5 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blue800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.824", + "green" : "0.463", + "red" : "0.098" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blueDark200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blueDark200.colorset/Contents.json new file mode 100644 index 0000000..e29b366 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blueDark200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.855", + "green" : "0.659", + "red" : "0.624" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blueDark300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blueDark300.colorset/Contents.json new file mode 100644 index 0000000..096e5f1 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blueDark300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.796", + "green" : "0.525", + "red" : "0.475" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blueDark500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blueDark500.colorset/Contents.json new file mode 100644 index 0000000..22f8cb4 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blueDark500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.710", + "green" : "0.318", + "red" : "0.247" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blueDark800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blueDark800.colorset/Contents.json new file mode 100644 index 0000000..bf615f8 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blueDark800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.624", + "green" : "0.247", + "red" : "0.188" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blueLight200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blueLight200.colorset/Contents.json new file mode 100644 index 0000000..1ded918 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blueLight200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.980", + "green" : "0.831", + "red" : "0.506" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blueLight300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blueLight300.colorset/Contents.json new file mode 100644 index 0000000..f17585c --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blueLight300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.969", + "green" : "0.765", + "red" : "0.310" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blueLight500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blueLight500.colorset/Contents.json new file mode 100644 index 0000000..9453b24 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blueLight500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.957", + "green" : "0.663", + "red" : "0.012" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/blueLight800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/blueLight800.colorset/Contents.json new file mode 100644 index 0000000..2b85944 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/blueLight800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.820", + "green" : "0.533", + "red" : "0.008" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/brown200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/brown200.colorset/Contents.json new file mode 100644 index 0000000..ce0b7bb --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/brown200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.643", + "green" : "0.667", + "red" : "0.737" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/brown300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/brown300.colorset/Contents.json new file mode 100644 index 0000000..957f0da --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/brown300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.498", + "green" : "0.533", + "red" : "0.631" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/brown500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/brown500.colorset/Contents.json new file mode 100644 index 0000000..2926f1b --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/brown500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.282", + "green" : "0.333", + "red" : "0.475" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/brown800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/brown800.colorset/Contents.json new file mode 100644 index 0000000..70e2f7c --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/brown800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.216", + "green" : "0.251", + "red" : "0.365" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenDark100.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark100.colorset/Contents.json new file mode 100644 index 0000000..72469b0 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark100.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "201", + "green" : "227", + "red" : "199" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenDark200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark200.colorset/Contents.json new file mode 100644 index 0000000..c7b6100 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "167", + "green" : "214", + "red" : "165" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenDark300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark300.colorset/Contents.json new file mode 100644 index 0000000..0f3b846 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "132", + "green" : "199", + "red" : "129" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenDark500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark500.colorset/Contents.json new file mode 100644 index 0000000..ddfea69 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.314", + "green" : "0.686", + "red" : "0.298" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenDark800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark800.colorset/Contents.json new file mode 100644 index 0000000..9dbb7a6 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenDark800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.235", + "green" : "0.557", + "red" : "0.220" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenLight200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenLight200.colorset/Contents.json new file mode 100644 index 0000000..54f6a97 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenLight200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.647", + "green" : "0.882", + "red" : "0.773" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenLight300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenLight300.colorset/Contents.json new file mode 100644 index 0000000..2c4fe10 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenLight300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.506", + "green" : "0.835", + "red" : "0.682" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenLight500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenLight500.colorset/Contents.json new file mode 100644 index 0000000..89db920 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenLight500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.290", + "green" : "0.765", + "red" : "0.545" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/greenLight800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/greenLight800.colorset/Contents.json new file mode 100644 index 0000000..1acd954 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/greenLight800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.220", + "green" : "0.624", + "red" : "0.408" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark200.colorset/Contents.json new file mode 100644 index 0000000..ef9328c --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.859", + "green" : "0.616", + "red" : "0.702" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark300.colorset/Contents.json new file mode 100644 index 0000000..3556135 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.804", + "green" : "0.459", + "red" : "0.584" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark500.colorset/Contents.json new file mode 100644 index 0000000..00e5075 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.718", + "green" : "0.227", + "red" : "0.404" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark800.colorset/Contents.json new file mode 100644 index 0000000..748a957 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/magentaDark800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.659", + "green" : "0.176", + "red" : "0.318" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight200.colorset/Contents.json new file mode 100644 index 0000000..725c54c --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.847", + "green" : "0.576", + "red" : "0.808" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight300.colorset/Contents.json new file mode 100644 index 0000000..d9fbdb8 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.784", + "green" : "0.408", + "red" : "0.729" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight500.colorset/Contents.json new file mode 100644 index 0000000..99500b7 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.690", + "green" : "0.153", + "red" : "0.612" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight800.colorset/Contents.json new file mode 100644 index 0000000..2921caf --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/magentaLight800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.635", + "green" : "0.122", + "red" : "0.482" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark200.colorset/Contents.json new file mode 100644 index 0000000..fbe5e38 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.569", + "green" : "0.671", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark300.colorset/Contents.json new file mode 100644 index 0000000..58e2f9f --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.396", + "green" : "0.541", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark500.colorset/Contents.json new file mode 100644 index 0000000..e219ac8 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.133", + "green" : "0.341", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark800.colorset/Contents.json new file mode 100644 index 0000000..a63dd3e --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/orangeDark800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.098", + "green" : "0.290", + "red" : "0.902" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight200.colorset/Contents.json new file mode 100644 index 0000000..6e70cd5 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.502", + "green" : "0.800", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight300.colorset/Contents.json new file mode 100644 index 0000000..799505c --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.302", + "green" : "0.718", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight500.colorset/Contents.json new file mode 100644 index 0000000..4f0878b --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.596", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight800.colorset/Contents.json new file mode 100644 index 0000000..dfc0149 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/orangeLight800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.486", + "red" : "0.961" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/pink200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/pink200.colorset/Contents.json new file mode 100644 index 0000000..0becef6 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/pink200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.694", + "green" : "0.561", + "red" : "0.957" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/pink300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/pink300.colorset/Contents.json new file mode 100644 index 0000000..9e9e4b7 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/pink300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.573", + "green" : "0.384", + "red" : "0.941" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/pink500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/pink500.colorset/Contents.json new file mode 100644 index 0000000..ddc3e1d --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/pink500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.388", + "green" : "0.118", + "red" : "0.914" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/pink800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/pink800.colorset/Contents.json new file mode 100644 index 0000000..463aa83 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/pink800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.357", + "green" : "0.094", + "red" : "0.761" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/red200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/red200.colorset/Contents.json new file mode 100644 index 0000000..518a736 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/red200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.604", + "green" : "0.604", + "red" : "0.937" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/red300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/red300.colorset/Contents.json new file mode 100644 index 0000000..94100b6 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/red300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.451", + "green" : "0.451", + "red" : "0.898" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/red500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/red500.colorset/Contents.json new file mode 100644 index 0000000..7afafeb --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/red500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.212", + "green" : "0.263", + "red" : "0.957" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/red800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/red800.colorset/Contents.json new file mode 100644 index 0000000..8972c91 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/red800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.184", + "green" : "0.184", + "red" : "0.827" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark200.colorset/Contents.json new file mode 100644 index 0000000..89f27af --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.769", + "green" : "0.796", + "red" : "0.502" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark300.colorset/Contents.json new file mode 100644 index 0000000..39d4eca --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.675", + "green" : "0.714", + "red" : "0.302" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark500.colorset/Contents.json new file mode 100644 index 0000000..13174d8 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.533", + "green" : "0.588", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark800.colorset/Contents.json new file mode 100644 index 0000000..24f01a5 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseDark800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.420", + "green" : "0.475", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight200.colorset/Contents.json new file mode 100644 index 0000000..0f87be6 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.918", + "green" : "0.871", + "red" : "0.502" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight300.colorset/Contents.json new file mode 100644 index 0000000..5d7af98 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.882", + "green" : "0.816", + "red" : "0.302" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight500.colorset/Contents.json new file mode 100644 index 0000000..20a4a22 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.831", + "green" : "0.737", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight800.colorset/Contents.json new file mode 100644 index 0000000..68b5f8d --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/tortoiseLight800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.655", + "green" : "0.592", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark200.colorset/Contents.json new file mode 100644 index 0000000..98fa97f --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.510", + "green" : "0.878", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark300.colorset/Contents.json new file mode 100644 index 0000000..6140117 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.310", + "green" : "0.835", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark500.colorset/Contents.json new file mode 100644 index 0000000..6ef924c --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.027", + "green" : "0.757", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark800.colorset/Contents.json new file mode 100644 index 0000000..93e32b7 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/yellowDark800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.627", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight200.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight200.colorset/Contents.json new file mode 100644 index 0000000..f1b174f --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.612", + "green" : "0.933", + "red" : "0.902" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight300.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight300.colorset/Contents.json new file mode 100644 index 0000000..74aa8a8 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight300.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.459", + "green" : "0.906", + "red" : "0.863" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight500.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight500.colorset/Contents.json new file mode 100644 index 0000000..ac7f58f --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight500.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.224", + "green" : "0.863", + "red" : "0.804" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight800.colorset/Contents.json b/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight800.colorset/Contents.json new file mode 100644 index 0000000..8aa0219 --- /dev/null +++ b/old/Resources/Assets/Colors.xcassets/rainbow/yellowLight800.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.169", + "green" : "0.706", + "red" : "0.686" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Images.xcassets/AppIcon.appiconset/Contents.json b/old/Resources/Assets/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..72c4225 --- /dev/null +++ b/old/Resources/Assets/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "logo2.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Images.xcassets/AppIcon.appiconset/logo2.png b/old/Resources/Assets/Images.xcassets/AppIcon.appiconset/logo2.png new file mode 100644 index 0000000..0eb8723 Binary files /dev/null and b/old/Resources/Assets/Images.xcassets/AppIcon.appiconset/logo2.png differ diff --git a/old/Resources/Assets/Images.xcassets/Contents.json b/old/Resources/Assets/Images.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/old/Resources/Assets/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Assets/Images.xcassets/logo.imageset/Contents.json b/old/Resources/Assets/Images.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..aed7690 --- /dev/null +++ b/old/Resources/Assets/Images.xcassets/logo.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "logo2_wo_bg.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/old/Resources/Assets/Images.xcassets/logo.imageset/logo2_wo_bg.png b/old/Resources/Assets/Images.xcassets/logo.imageset/logo2_wo_bg.png new file mode 100644 index 0000000..e8e80f9 Binary files /dev/null and b/old/Resources/Assets/Images.xcassets/logo.imageset/logo2_wo_bg.png differ diff --git a/old/Resources/Preview Content/Preview Assets.xcassets/Contents.json b/old/Resources/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/old/Resources/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/old/Resources/Strings/Localizable.strings b/old/Resources/Strings/Localizable.strings new file mode 100644 index 0000000..8458afc --- /dev/null +++ b/old/Resources/Strings/Localizable.strings @@ -0,0 +1,76 @@ +// MARK: General +"Global.name" = "Conversartions Classic"; +"Global.ok" = "Ok"; +"Global.back" = "Back"; +"Global.cancel" = "Cancel"; +"Global.save" = "Save"; +"Global.Error.title" = "Error"; +"Global.Error.genericText" = "Something went wrong"; +"Global.Error.genericDbError" = "Database error"; + +// MARK: Onboar screen +"Start.subtitle" = "Free and secure messaging and calls between any existed messengers"; +"Start.Btn.login" = "Enter with JID"; +"Start.Btn.register" = "New Account"; +"Login.title" = "Let\'s go!"; +"Login.subtitle" = "Enter your JID, it should looks like email address"; +"Login.Hint.jid" = "user@domain.im"; +"Login.Hint.password" = "password"; +"Login.btn" = "Continue"; +"Login.Error.wrongPassword" = "Wrong password or JID"; +"Login.Error.noServer" = "Server not exists"; +"Login.Error.serverError" = "Server error. Check internet connection"; + +// MARK: Contacts screen +"Contacts.title" = "Contacts"; +"Contacts.sendMessage" = "Send message"; +"Contacts.editContact" = "Edit contact"; +"Contacts.selectContact" = "Select contact"; +"Contacts.deleteContact" = "Delete contact"; +"Contacts.Add.title" = "Add Contact"; +"Contacts.Add.explanation" = "Contact or group/channel name are usually JID in format name@domain.ltd (like email)"; +"Contacts.Add.error" = "Contact not added. Server returns error."; +"Contacts.Delete.title" = "Delete contact"; +"Contacts.Delete.message" = "You can delete contact from this device (contact will be available on other devices), or delete it completely"; +"Contacts.Delete.deleteFromDevice" = "Delete from device"; +"Contacts.Delete.deleteCompletely" = "Delete completely"; +"Contacts.Delete.error" = "Contact not deleted. Server returns error."; + + +// MARK: Chats screen +"Chats.title" = "Chats"; + +"Chat.title" = "Chat"; +"Chat.textfieldPrompt" = "Type a message"; + +"Chats.Create.Main.title" = "Create"; +"Chats.Create.Main.createGroup" = "Create public group"; +"Chats.Create.Main.createPrivateGroup" = "Create private group"; +"Chats.Create.Main.findGroup" = "Find public group"; + +// MARK: Accounts add screen +"Accounts.Add.or" = "or"; +"Accounts.Add.Exist.title" = "Add existing\naccount"; +"Accounts.Add.Exist.Prompt.jid" = "Enter your XMPP ID"; +"Accounts.Add.Exist.Prompt.password" = "Enter password"; +"Accounts.Add.Exist.Hint.jid" = "user@domain.im"; +"Accounts.Add.Exist.Hint.password" = "password"; +"Accounts.Add.Exist.Btn.link" = "create a new one"; +"Accounts.Add.Exist.Btn.main" = "Continue"; +"Accounts.Add.Exist.loginError" = "Wrong login or password"; + +// MARK: Server connecting indicator +"ServerConnectingIndicator.State.connecting" = "Connecting to server"; +"ServerConnectingIndicator.State.connected" = "Connected"; +"ServerConnectingIndicator.State.error" = "Server unreachable. Check internet connection and server name"; + +// MARK: Attachments +"Attachment.Prompt.main" = "Select attachment"; +"Attachment.Tab.media" = "Media"; +"Attachment.Tab.files" = "Files"; +"Attachment.Tab.location" = "Location"; +"Attachment.Tab.contacts" = "Contacts"; +"Attachment.Send.media" = "Send media"; +"Attachment.Send.location" = "Send location"; +"Attachment.Send.contact" = "Send contact"; +"Attachment.Downloading.retry" = "Retry"; diff --git a/old/Resources/launchscreen.storyboard b/old/Resources/launchscreen.storyboard new file mode 100644 index 0000000..ed88f70 --- /dev/null +++ b/old/Resources/launchscreen.storyboard @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/old/Resources/server_features.plist b/old/Resources/server_features.plist new file mode 100644 index 0000000..9fa58d6 --- /dev/null +++ b/old/Resources/server_features.plist @@ -0,0 +1,6598 @@ + + + + + + xep + XEP-0001 + name + XMPP Extension Protocols + type + Procedural + status + Active + date + 2016-11-16 + description + + xmppId + + + + xep + XEP-0002 + name + Special Interest Groups (SIGs) + type + Procedural + status + Active + date + 2002-01-11 + description + + xmppId + + + + xep + XEP-0003 + name + Proxy Accept Socket Service (PASS) + type + Historical + status + Obsolete + date + 2009-06-03 + description + + xmppId + jabber:iq:pass + + + xep + XEP-0004 + name + Data Forms + type + Standards Track + status + Final + date + 2007-08-13 + description + + xmppId + + + + xep + XEP-0005 + name + Jabber Interest Groups + type + Informational + status + Obsolete + date + 2002-05-08 + description + + xmppId + + + + xep + XEP-0006 + name + Profiles + type + SIG Formation + status + Obsolete + date + 2002-05-08 + description + + xmppId + + + + xep + XEP-0007 + name + Conferencing SIG + type + SIG Proposal + status + Obsolete + date + 2002-05-08 + description + + xmppId + + + + xep + XEP-0008 + name + IQ-Based Avatars + type + Historical + status + Deferred + date + 2005-06-16 + description + + xmppId + jabber:x:avatar + + + xep + XEP-0009 + name + Jabber-RPC + type + Standards Track + status + Final + date + 2011-11-10 + description + + xmppId + jabber:iq:rpc + + + xep + XEP-0010 + name + Whiteboarding SIG + type + SIG Formation + status + Obsolete + date + 2002-05-08 + description + + xmppId + + + + xep + XEP-0011 + name + Jabber Browsing + type + Historical + status + Obsolete + date + 2009-06-03 + description + + xmppId + jabber:iq:browse + + + xep + XEP-0012 + name + Last Activity + type + Standards Track + status + Final + date + 2008-11-26 + description + + xmppId + jabber:iq:last + + + xep + XEP-0013 + name + Flexible Offline Message Retrieval + type + Standards Track + status + Draft + date + 2005-07-14 + description + + xmppId + http://jabber.org/protocol/offline + + + xep + XEP-0014 + name + Message Tone + type + Standards Track + status + Rejected + date + 2002-01-16 + description + + xmppId + jabber:x:tone + + + xep + XEP-0015 + name + Account Transfer + type + Standards Track + status + Rejected + date + 2002-04-18 + description + + xmppId + jabber:iq:accountxfer + + + xep + XEP-0016 + name + Privacy Lists + type + Standards Track + status + Deprecated + date + 2017-05-20 + description + + xmppId + jabber:iq:privacy + + + xep + XEP-0017 + name + Naive Packet Framing Protocol + type + Informational + status + Rejected + date + 2002-02-19 + description + + xmppId + + + + xep + XEP-0018 + name + Invisible Presence + type + Informational + status + Rejected + date + 2003-09-26 + description + + xmppId + + + + xep + XEP-0019 + name + Streamlining the SIGs + type + Procedural + status + Active + date + 2002-03-20 + description + + xmppId + + + + xep + XEP-0020 + name + Feature Negotiation + type + Standards Track + status + Deprecated + date + 2018-03-07 + description + + xmppId + http://jabber.org/protocol/feature-neg + + + xep + XEP-0021 + name + Jabber Event Notification Service (ENS) + type + Standards Track + status + Retracted + date + 2003-04-22 + description + + xmppId + http://xml.cataclysm.cx/jabber/ens/ + + + xep + XEP-0022 + name + Message Events + type + Historical + status + Obsolete + date + 2009-05-27 + description + + xmppId + jabber:x:event + + + xep + XEP-0023 + name + Message Expiration + type + Historical + status + Obsolete + date + 2009-06-03 + description + + xmppId + + + + xep + XEP-0024 + name + Publish/Subscribe + type + Standards Track + status + Retracted + date + 2003-04-22 + description + + xmppId + jabber:iq:pubsub + + + xep + XEP-0025 + name + Jabber HTTP Polling + type + Historical + status + Obsolete + date + 2009-06-03 + description + + xmppId + + + + xep + XEP-0026 + name + Internationalization (I18N) + type + Standards Track + status + Retracted + date + 2003-11-05 + description + + xmppId + + + + xep + XEP-0027 + name + Current Jabber OpenPGP Usage + type + Historical + status + Obsolete + date + 2014-03-14 + description + + xmppId + + + + xep + XEP-0028 + name + No Such XEP + type + Informational + status + Retracted + date + 2001-08-20 + description + + xmppId + + + + xep + XEP-0029 + name + Definition of Jabber Identifiers (JIDs) + type + Standards Track + status + Retracted + date + 2003-10-03 + description + + xmppId + + + + xep + XEP-0030 + name + Service Discovery + type + Standards Track + status + Final + date + 2017-10-03 + description + + xmppId + http://jabber.org/protocol/disco* + + + xep + XEP-0031 + name + A Framework For Securing Jabber Conversations + type + Standards Track + status + Deferred + date + 2002-07-09 + description + + xmppId + + + + xep + XEP-0032 + name + Jabber URI Scheme + type + Standards Track + status + Retracted + date + 2003-09-02 + description + + xmppId + + + + xep + XEP-0033 + name + Extended Stanza Addressing + type + Standards Track + status + Draft + date + 2017-01-11 + description + + xmppId + http://jabber.org/protocol/address + + + xep + XEP-0034 + name + SASL Integration + type + Standards Track + status + Retracted + date + 2003-11-05 + description + + xmppId + + + + xep + XEP-0035 + name + SSL/TLS Integration + type + Standards Track + status + Retracted + date + 2003-11-05 + description + + xmppId + + + + xep + XEP-0036 + name + Pub-Sub Subscriptions + type + Standards Track + status + Retracted + date + 2003-04-22 + description + + xmppId + jabber:iq:pubsub + + + xep + XEP-0037 + name + DSPS - Data Stream Proxy Service + type + Standards Track + status + Rejected + date + 2016-10-04 + description + + xmppId + + + + xep + XEP-0038 + name + Icon Styles + type + Standards Track + status + Deferred + date + 2003-06-02 + description + + xmppId + + + + xep + XEP-0039 + name + Statistics Gathering + type + Standards Track + status + Deferred + date + 2002-11-05 + description + + xmppId + http://jabber.org/protocol/stats + + + xep + XEP-0040 + name + Jabber Robust Publish-Subscribe + type + Standards Track + status + Retracted + date + 2004-07-26 + description + + xmppId + + + + xep + XEP-0041 + name + Reliable Entity Link + type + Standards Track + status + Retracted + date + 2003-09-30 + description + + xmppId + http://jabber.org/protocol/rel + + + xep + XEP-0042 + name + Jabber OOB Broadcast Service (JOBS) + type + Standards Track + status + Retracted + date + 2003-04-11 + description + + xmppId + http://jabber.org/protocol/jobs + + + xep + XEP-0043 + name + Jabber Database Access + type + Standards Track + status + Retracted + date + 2003-10-20 + description + + xmppId + http://openaether.org/projects/jabber_database.html + + + xep + XEP-0044 + name + Full Namespace Support for XML Streams + type + Standards Track + status + Deferred + date + 2002-08-26 + description + + xmppId + + + + xep + XEP-0045 + name + Multi-User Chat + type + Standards Track + status + Draft + date + 2018-07-31 + description + + xmppId + http://jabber.org/protocol/muc + + + xep + XEP-0046 + name + DTCP + type + Standards Track + status + Retracted + date + 2003-04-11 + description + + xmppId + http://jabber.org/protocol/dtcp + + + xep + XEP-0047 + name + In-Band Bytestreams + type + Standards Track + status + Final + date + 2012-06-22 + description + + xmppId + http://jabber.org/protocol/ibb + + + xep + XEP-0048 + name + Bookmarks + type + Standards Track + status + Draft + date + 2007-11-07 + description + + xmppId + storage:bookmarks + + + xep + XEP-0049 + name + Private XML Storage + type + Historical + status + Active + date + 2004-03-01 + description + + xmppId + jabber:iq:private + + + xep + XEP-0050 + name + Ad-Hoc Commands + type + Standards Track + status + Draft + date + 2016-12-03 + description + + xmppId + http://jabber.org/protocol/commands + + + xep + XEP-0051 + name + Connection Transfer + type + Standards Track + status + Deferred + date + 2009-07-07 + description + + xmppId + urn:xmpp:cxfr + + + xep + XEP-0052 + name + File Transfer + type + Standards Track + status + Retracted + date + 2003-09-30 + description + + xmppId + http://jabber.org/protocol/feature-neg + + + xep + XEP-0053 + name + XMPP Registrar Function + type + Procedural + status + Active + date + 2016-12-01 + description + + xmppId + + + + xep + XEP-0054 + name + vcard-temp + type + Historical + status + Active + date + 2008-07-16 + description + + xmppId + vcard-temp + + + xep + XEP-0055 + name + Jabber Search + type + Historical + status + Active + date + 2009-09-15 + description + + xmppId + jabber:iq:search + + + xep + XEP-0056 + name + Business Data Interchange + type + Standards Track + status + Deferred + date + 2002-11-18 + description + + xmppId + http://jabber.org/protocol/ebxml + + + xep + XEP-0057 + name + Extended Roster + type + Standards Track + status + Retracted + date + 2003-04-28 + description + + xmppId + + + + xep + XEP-0058 + name + Multi-User Text Editing + type + Standards Track + status + Deferred + date + 2002-11-12 + description + + xmppId + + + + xep + XEP-0059 + name + Result Set Management + type + Standards Track + status + Draft + date + 2006-09-20 + description + + xmppId + http://jabber.org/protocol/rsm + + + xep + XEP-0060 + name + Publish-Subscribe + type + Standards Track + status + Draft + date + 2018-05-14 + description + + xmppId + http://jabber.org/protocol/pubsub + + + xep + XEP-0061 + name + Shared Notes + type + Informational + status + Deferred + date + 2003-09-30 + description + + xmppId + http://www.jabber.org/protocol/sharednote + + + xep + XEP-0062 + name + Packet Filtering + type + Informational + status + Deferred + date + 2003-09-30 + description + + xmppId + http://jabber.org/protocol/filter + + + xep + XEP-0063 + name + Basic Filtering Operations + type + Informational + status + Deferred + date + 2003-09-30 + description + + xmppId + http://jabber.org/protocol/filter/basic + + + xep + XEP-0064 + name + XPath Filtering + type + Informational + status + Deferred + date + 2003-09-30 + description + + xmppId + http://jabber.org/protocol/filter/xpath + + + xep + XEP-0065 + name + SOCKS5 Bytestreams + type + Standards Track + status + Draft + date + 2015-09-17 + description + + xmppId + http://jabber.org/protocol/bytestreams + + + xep + XEP-0065 + name + Out of Band Data + type + Standards Track + status + Draft + date + 2006-08-15 + description + + xmppId + jabber:x:oob + + + xep + XEP-0066 + name + Out of Band Data + type + Standards Track + status + Draft + date + 2006-08-16 + description + + xmppId + jabber:iq:oob + + + xep + XEP-0067 + name + Stock Data Transmission + type + Standards Track + status + Deferred + date + 2003-07-19 + description + + xmppId + + + + xep + XEP-0068 + name + Field Standardization for Data Forms + type + Informational + status + Active + date + 2012-05-28 + description + + xmppId + + + + xep + XEP-0069 + name + Compliance SIG + type + SIG Formation + status + Deferred + date + 2003-01-29 + description + + xmppId + + + + xep + XEP-0070 + name + Verifying HTTP Requests via XMPP + type + Standards Track + status + Draft + date + 2016-12-09 + description + + xmppId + http://jabber.org/protocol/http-auth + + + xep + XEP-0071 + name + XHTML-IM + type + Standards Track + status + Deprecated + date + 2018-03-08 + description + + xmppId + http://jabber.org/protocol/xhtml-im + + + xep + XEP-0072 + name + SOAP Over XMPP + type + Standards Track + status + Draft + date + 2005-12-14 + description + + xmppId + http://jabber.org/protocol/soap + + + xep + XEP-0073 + name + Basic IM Protocol Suite + type + Standards Track + status + Obsolete + date + 2007-10-30 + description + + xmppId + + + + xep + XEP-0074 + name + Simple Access Control + type + Standards Track + status + Retracted + date + 2003-10-20 + description + + xmppId + http://jabber.org/protocol/sac + + + xep + XEP-0075 + name + Jabber Object Access Protocol (JOAP) + type + Standards Track + status + Deferred + date + 2003-05-22 + description + + xmppId + jabber:iq:joap + + + xep + XEP-0076 + name + Malicious Stanzas + type + Humorous + status + Active + date + 2003-04-01 + description + + xmppId + http://jabber.org/protocol/evil + + + xep + XEP-0077 + name + In-Band Registration + type + Standards Track + status + Final + date + 2012-01-25 + description + + xmppId + jabber:iq:register + + + xep + XEP-0078 + name + Non-SASL Authentication + type + Standards Track + status + Obsolete + date + 2008-10-29 + description + + xmppId + jabber:iq:auth + + + xep + XEP-0079 + name + Advanced Message Processing + type + Standards Track + status + Draft + date + 2005-11-30 + description + + xmppId + http://jabber.org/protocol/amp + + + xep + XEP-0080 + name + User Location + type + Standards Track + status + Draft + date + 2015-12-01 + description + + xmppId + http://jabber.org/protocol/geoloc + + + xep + XEP-0081 + name + Jabber MIME Type + type + Standards Track + status + Retracted + date + 2005-07-19 + description + + xmppId + + + + xep + XEP-0082 + name + XMPP Date and Time Profiles + type + Informational + status + Active + date + 2013-09-26 + description + + xmppId + + + + xep + XEP-0083 + name + Nested Roster Groups + type + Informational + status + Active + date + 2004-10-11 + description + + xmppId + roster:delimiter + + + xep + XEP-0084 + name + User Avatar + type + Standards Track + status + Draft + date + 2016-07-09 + description + + xmppId + + + + xep + XEP-0085 + name + Chat State Notifications + type + Standards Track + status + Final + date + 2009-09-23 + description + + xmppId + http://jabber.org/protocol/chatstates + + + xep + XEP-0086 + name + Error Condition Mappings + type + Informational + status + Deprecated + date + 2004-02-17 + description + + xmppId + + + + xep + XEP-0087 + name + Stream Initiation + type + Standards Track + status + Retracted + date + 2003-05-22 + description + + xmppId + http://jabber.org/protocol/si + + + xep + XEP-0088 + name + Client Webtabs + type + Informational + status + Deferred + date + 2004-03-14 + description + + xmppId + http://jabber.org/protocol/webtab + + + xep + XEP-0089 + name + Generic Alerts + type + Standards Track + status + Deferred + date + 2003-05-16 + description + + xmppId + http://jabber.org/protocol/alert + + + xep + XEP-0090 + name + Legacy Entity Time + type + Historical + status + Obsolete + date + 2009-05-27 + description + + xmppId + jabber:iq:time + + + xep + XEP-0091 + name + Legacy Delayed Delivery + type + Historical + status + Obsolete + date + 2009-05-27 + description + + xmppId + jabber:x:delay + + + xep + XEP-0092 + name + Software Version + type + Standards Track + status + Draft + date + 2007-02-15 + description + + xmppId + jabber:iq:version + + + xep + XEP-0093 + name + Roster Item Exchange + type + Historical + status + Deprecated + date + 2005-08-26 + description + + xmppId + + + + xep + XEP-0094 + name + Agent Information + type + Historical + status + Obsolete + date + 2003-10-08 + description + + xmppId + jabber:iq:agents + + + xep + XEP-0095 + name + Stream Initiation + type + Standards Track + status + Deprecated + date + 2017-11-29 + description + + xmppId + http://jabber.org/protocol/si + + + xep + XEP-0096 + name + SI File Transfer + type + Standards Track + status + Deprecated + date + 2017-11-29 + description + + xmppId + http://jabber.org/protocol/si/profile/file-transfer + + + xep + XEP-0097 + name + iCal Envelope + type + Standards Track + status + Deferred + date + 2003-06-10 + description + + xmppId + http://jabber.org/protocol/gw/ical + + + xep + XEP-0098 + name + Enhanced Private XML Storage + type + Standards Track + status + Deferred + date + 2003-06-25 + description + + xmppId + http://jabber.org/protocol/private-xml + + + xep + XEP-0099 + name + IQ Query Action Protocol + type + Standards Track + status + Deferred + date + 2003-06-25 + description + + xmppId + + + + xep + XEP-0100 + name + Gateway Interaction + type + Informational + status + Active + date + 2005-10-05 + description + + xmppId + + + + xep + XEP-0101 + name + HTTP Authentication using Jabber Tickets + type + Standards Track + status + Deferred + date + 2004-01-18 + description + + xmppId + + + + xep + XEP-0102 + name + Security Extensions + type + Standards Track + status + Deferred + date + 2003-06-25 + description + + xmppId + xmpp:sec + + + xep + XEP-0103 + name + URL Address Information + type + Standards Track + status + Deferred + date + 2004-01-20 + description + + xmppId + + + + xep + XEP-0104 + name + HTTP Scheme for URL Data + type + Standards Track + status + Deferred + date + 2004-01-20 + description + + xmppId + + + + xep + XEP-0105 + name + Tree Transfer Stream Initiation Profile + type + Standards Track + status + Deferred + date + 2003-09-22 + description + + xmppId + + + + xep + XEP-0106 + name + JID Escaping + type + Standards Track + status + Draft + date + 2016-07-08 + description + + xmppId + jid\20escaping + + + xep + XEP-0107 + name + User Mood + type + Standards Track + status + Draft + date + 2018-03-13 + description + + xmppId + http://jabber.org/protocol/mood + + + xep + XEP-0108 + name + User Activity + type + Standards Track + status + Draft + date + 2008-10-29 + description + + xmppId + http://jabber.org/protocol/activity + + + xep + XEP-0109 + name + Out-of-Office Messages + type + Standards Track + status + Deferred + date + 2010-05-24 + description + + xmppId + + + + xep + XEP-0110 + name + Generic Maps + type + Standards Track + status + Deferred + date + 2003-07-28 + description + + xmppId + http://jabber.org/protocol/map + + + xep + XEP-0111 + name + A Transport for Initiating and Negotiating Sessions (TINS) + type + Standards Track + status + Retracted + date + 2005-12-21 + description + + xmppId + http://jabber.org/protocol/tins + + + xep + XEP-0112 + name + User Physical Location + type + Standards Track + status + Obsolete + date + 2004-10-12 + description + + xmppId + http://jabber.org/protocol/physloc + + + xep + XEP-0113 + name + Simple Whiteboarding + type + Informational + status + Deferred + date + 2003-09-07 + description + + xmppId + http://jabber.org/protocol/swb + + + xep + XEP-0114 + name + Jabber Component Protocol + type + Historical + status + Active + date + 2012-01-25 + description + + xmppId + + + + xep + XEP-0115 + name + Entity Capabilities + type + Standards Track + status + Draft + date + 2016-10-06 + description + + xmppId + http://jabber.org/protocol/caps + + + xep + XEP-0116 + name + Encrypted Session Negotiation + type + Standards Track + status + Deferred + date + 2007-05-30 + description + + xmppId + http://www.xmpp.org/extensions/xep-0116.html#ns + + + xep + XEP-0117 + name + Intermediate IM Protocol Suite + type + Standards Track + status + Obsolete + date + 2007-10-30 + description + + xmppId + + + + xep + XEP-0118 + name + User Tune + type + Standards Track + status + Draft + date + 2008-01-30 + description + + xmppId + http://jabber.org/protocol/tune + + + xep + XEP-0119 + name + Extended Presence Protocol Suite + type + Standards Track + status + Retracted + date + 2006-08-08 + description + + xmppId + + + + xep + XEP-0120 + name + Infobits + type + Standards Track + status + Retracted + date + 2004-01-22 + description + + xmppId + http://jabber.org/protocol/infobits + + + xep + XEP-0121 + name + Dublin Core Infobits Mapping + type + Informational + status + Retracted + date + 2003-12-15 + description + + xmppId + + + + xep + XEP-0122 + name + Data Forms Validation + type + Standards Track + status + Draft + date + 2018-03-21 + description + + xmppId + http://jabber.org/protocol/xdata-validate + + + xep + XEP-0123 + name + Entity Metadata + type + Standards Track + status + Retracted + date + 2003-12-16 + description + + xmppId + + + + xep + XEP-0124 + name + Bidirectional-streams Over Synchronous HTTP (BOSH) + type + Standards Track + status + Draft + date + 2016-11-16 + description + + xmppId + + + + xep + XEP-0125 + name + vCard Infobits Mapping + type + Informational + status + Retracted + date + 2003-12-15 + description + + xmppId + + + + xep + XEP-0126 + name + Invisibility + type + Informational + status + Deprecated + date + 2005-08-19 + description + + xmppId + + + + xep + XEP-0127 + name + Common Alerting Protocol (CAP) Over XMPP + type + Informational + status + Active + date + 2004-12-09 + description + + xmppId + http://www.incident.com/cap/1.0 + + + xep + XEP-0128 + name + Service Discovery Extensions + type + Informational + status + Active + date + 2004-10-20 + description + + xmppId + + + + xep + XEP-0129 + name + WebDAV File Transfers + type + Standards Track + status + Deferred + date + 2007-04-19 + description + + xmppId + http://www.xmpp.org/extensions/xep-0129.html#ns + + + xep + XEP-0130 + name + Waiting Lists + type + Historical + status + Deprecated + date + 2012-04-18 + description + + xmppId + http://jabber.org/protocol/waitinglist + + + xep + XEP-0131 + name + Stanza Headers and Internet Metadata + type + Standards Track + status + Draft + date + 2006-07-12 + description + + xmppId + http://jabber.org/protocol/shim + + + xep + XEP-0132 + name + Presence Obtained via Kinesthetic Excitation (POKE) + type + Humorous + status + Active + date + 2004-04-01 + description + + xmppId + http://jabber.org/protocol/poke + + + xep + XEP-0133 + name + Service Administration + type + Informational + status + Active + date + 2017-07-15 + description + + xmppId + + + + xep + XEP-0134 + name + XMPP Design Guidelines + type + Informational + status + Active + date + 2004-12-09 + description + + xmppId + + + + xep + XEP-0135 + name + File Sharing + type + Standards Track + status + Deferred + date + 2004-06-04 + description + + xmppId + http://jabber.org/protocol/files + + + xep + XEP-0136 + name + Message Archiving + type + Standards Track + status + Deprecated + date + 2017-11-15 + description + + xmppId + urn:xmpp:archive* + + + xep + XEP-0137 + name + Publishing Stream Initiation Requests + type + Standards Track + status + Deprecated + date + 2018-02-28 + description + + xmppId + http://jabber.org/protocol/sipub + + + xep + XEP-0138 + name + Stream Compression + type + Standards Track + status + Final + date + 2009-05-27 + description + + xmppId + http://jabber.org/features/compress + + + xep + XEP-0139 + name + Security SIG + type + SIG Formation + status + Retracted + date + 2004-09-15 + description + + xmppId + + + + xep + XEP-0140 + name + Shared Groups + type + Informational + status + Retracted + date + 2004-10-27 + description + + xmppId + + + + xep + XEP-0141 + name + Data Forms Layout + type + Standards Track + status + Draft + date + 2005-05-12 + description + + xmppId + + + + xep + XEP-0142 + name + Workgroup Queues + type + Standards Track + status + Deferred + date + 2005-05-09 + description + + xmppId + http://jabber.org/protocol/workgroup + + + xep + XEP-0143 + name + Guidelines for Authors of XMPP Extension Protocols + type + Procedural + status + Active + date + 2016-12-02 + description + + xmppId + + + + xep + XEP-0144 + name + Roster Item Exchange + type + Standards Track + status + Draft + date + 2017-11-28 + description + + xmppId + http://jabber.org/protocol/rosterx + + + xep + XEP-0145 + name + Annotations + type + Historical + status + Active + date + 2006-03-23 + description + + xmppId + + + + xep + XEP-0146 + name + Remote Controlling Clients + type + Informational + status + Obsolete + date + 2017-11-07 + description + + xmppId + http://jabber.org/protocol/rc* + + + xep + XEP-0147 + name + XMPP URI Scheme Query Components + type + Informational + status + Active + date + 2006-09-13 + description + + xmppId + + + + xep + XEP-0148 + name + Instant Messaging Intelligence Quotient (IM IQ) + type + Humorous + status + Active + date + 2005-04-01 + description + + xmppId + jabber:iq:iq + + + xep + XEP-0149 + name + Time Periods + type + Informational + status + Active + date + 2006-01-24 + description + + xmppId + + + + xep + XEP-0150 + name + Use of Entity Tags in XMPP Extensions + type + Informational + status + Deferred + date + 2005-08-09 + description + + xmppId + + + + xep + XEP-0151 + name + Virtual Presence + type + Standards Track + status + Deferred + date + 2005-07-05 + description + + xmppId + + + + xep + XEP-0152 + name + Reachability Addresses + type + Standards Track + status + Draft + date + 2014-02-25 + description + + xmppId + urn:xmpp:reach:0 + + + xep + XEP-0153 + name + vCard-Based Avatars + type + Historical + status + Active + date + 2018-02-26 + description + + xmppId + + + + xep + XEP-0154 + name + User Profile + type + Standards Track + status + Deferred + date + 2008-04-18 + description + + xmppId + urn:xmpp:tmp:profile + + + xep + XEP-0155 + name + Stanza Session Negotiation + type + Standards Track + status + Draft + date + 2016-01-20 + description + + xmppId + http://jabber.org/protocol/feature-neg + + + xep + XEP-0156 + name + Discovering Alternative XMPP Connection Methods + type + Standards Track + status + Draft + date + 2018-07-21 + description + + xmppId + + + + xep + XEP-0157 + name + Contact Addresses for XMPP Services + type + Informational + status + Active + date + 2018-07-21 + description + + xmppId + + + + xep + XEP-0158 + name + CAPTCHA Forms + type + Standards Track + status + Draft + date + 2008-09-03 + description + + xmppId + + + + xep + XEP-0159 + name + Spim-Blocking Control + type + Standards Track + status + Deferred + date + 2006-07-11 + description + + xmppId + http://www.xmpp.org/extensions/xep-0159.html* + + + xep + XEP-0160 + name + Best Practices for Handling Offline Messages + type + Informational + status + Active + date + 2016-10-07 + description + + xmppId + msgoffline + + + xep + XEP-0161 + name + Abuse Reporting + type + Standards Track + status + Deferred + date + 2007-05-06 + description + + xmppId + urn:xmpp:tmp:abuse + + + xep + XEP-0162 + name + Best Practices for Roster and Subscription Management + type + Informational + status + Deferred + date + 2005-12-06 + description + + xmppId + + + + xep + XEP-0163 + name + Personal Eventing Protocol + type + Standards Track + status + Draft + date + 2018-03-18 + description + + xmppId + + + + xep + XEP-0164 + name + vCard Filtering + type + Standards Track + status + Deferred + date + 2005-11-16 + description + + xmppId + + + + xep + XEP-0165 + name + Best Practices to Discourage JID Mimicking + type + Informational + status + Deferred + date + 2007-12-13 + description + + xmppId + + + + xep + XEP-0166 + name + Jingle + type + Standards Track + status + Draft + date + 2016-05-17 + description + + xmppId + urn:xmpp:jingle:1 + + + xep + XEP-0167 + name + Jingle RTP Sessions + type + Standards Track + status + Draft + date + 2016-07-08 + description + + xmppId + + + + xep + XEP-0168 + name + Resource Application Priority + type + Standards Track + status + Deferred + date + 2008-09-26 + description + + xmppId + urn:xmpp:rap:0 + + + xep + XEP-0169 + name + Twas The Night Before Christmas (Jabber Version) + type + Humorous + status + Active + date + 2009-12-24 + description + + xmppId + + + + xep + XEP-0170 + name + Recommended Order of Stream Feature Negotiation + type + Informational + status + Active + date + 2007-01-04 + description + + xmppId + + + + xep + XEP-0171 + name + Language Translation + type + Standards Track + status + Draft + date + 2015-10-15 + description + + xmppId + urn:xmpp:langtrans + + + xep + XEP-0172 + name + User Nickname + type + Standards Track + status + Draft + date + 2012-03-21 + description + + xmppId + http://jabber.org/protocol/nick + + + xep + XEP-0173 + name + Pubsub Subscription Storage + type + Historical + status + Deferred + date + 2006-02-09 + description + + xmppId + storage:pubsubs + + + xep + XEP-0174 + name + Serverless Messaging + type + Standards Track + status + Final + date + 2018-02-08 + description + + xmppId + + + + xep + XEP-0175 + name + Best Practices for Use of SASL ANONYMOUS + type + Informational + status + Active + date + 2009-09-30 + description + + xmppId + + + + xep + XEP-0176 + name + Jingle ICE-UDP Transport Method + type + Standards Track + status + Draft + date + 2009-06-10 + description + + xmppId + urn:xmpp:jingle:transports:ice-udp* + + + xep + XEP-0177 + name + Jingle Raw UDP Transport Method + type + Standards Track + status + Draft + date + 2009-12-23 + description + + xmppId + urn:xmpp:jingle:transports:raw-udp* + + + xep + XEP-0178 + name + Best Practices for Use of SASL EXTERNAL with Certificates + type + Informational + status + Active + date + 2011-05-25 + description + + xmppId + + + + xep + XEP-0179 + name + Jingle IAX Transport Method + type + Standards Track + status + Deferred + date + 2006-03-23 + description + + xmppId + + + + xep + XEP-0180 + name + Jingle Video via RTP + type + Standards Track + status + Retracted + date + 2008-06-04 + description + + xmppId + urn:xmpp:tmp:jingle:apps:video-rtp + + + xep + XEP-0181 + name + Jingle DTMF + type + Standards Track + status + Deferred + date + 2009-10-02 + description + + xmppId + + + + xep + XEP-0182 + name + Application-Specific Error Conditions + type + Procedural + status + Active + date + 2008-03-05 + description + + xmppId + + + + xep + XEP-0183 + name + Jingle Telepathy Transport + type + Humorous + status + Active + date + 2006-04-01 + description + + xmppId + + + + xep + XEP-0184 + name + Message Delivery Receipts + type + Standards Track + status + Draft + date + 2011-03-01 + description + + xmppId + urn:xmpp:receipts + + + xep + XEP-0185 + name + Dialback Key Generation and Validation + type + Informational + status + Active + date + 2007-02-15 + description + + xmppId + + + + xep + XEP-0186 + name + Invisible Command + type + Standards Track + status + Proposed + date + 2017-11-29 + description + + xmppId + urn:xmpp:invisible:1 + + + xep + XEP-0187 + name + Offline Encrypted Sessions + type + Standards Track + status + Deferred + date + 2007-05-30 + description + + xmppId + http://www.xmpp.org/extensions/xep-0187.html#ns + + + xep + XEP-0188 + name + Cryptographic Design of Encrypted Sessions + type + Informational + status + Deferred + date + 2007-05-30 + description + + xmppId + + + + xep + XEP-0189 + name + Public Key Publishing + type + Standards Track + status + Deferred + date + 2010-07-15 + description + + xmppId + urn:xmpp:pubkey:2 + + + xep + XEP-0190 + name + Best Practice for Closing Idle Streams + type + Informational + status + Obsolete + date + 2012-03-06 + description + + xmppId + + + + xep + XEP-0191 + name + Blocking Command + type + Standards Track + status + Draft + date + 2015-03-12 + description + + xmppId + urn:xmpp:blocking + + + xep + XEP-0192 + name + Proposed Stream Feature Improvements + type + Standards Track + status + Obsolete + date + 2012-02-08 + description + + xmppId + + + + xep + XEP-0193 + name + Proposed Resource Binding Improvements + type + Standards Track + status + Obsolete + date + 2012-02-08 + description + + xmppId + + + + xep + XEP-0194 + name + User Chatting + type + Standards Track + status + Deferred + date + 2008-09-25 + description + + xmppId + urn:xmpp:chatting:0 + + + xep + XEP-0195 + name + User Browsing + type + Standards Track + status + Deferred + date + 2008-09-25 + description + + xmppId + urn:xmpp:browsing:0 + + + xep + XEP-0196 + name + User Gaming + type + Standards Track + status + Deferred + date + 2008-09-25 + description + + xmppId + urn:xmpp:gaming:0 + + + xep + XEP-0197 + name + User Viewing + type + Standards Track + status + Deferred + date + 2008-09-25 + description + + xmppId + urn:xmpp:viewing:0 + + + xep + XEP-0198 + name + Stream Management + type + Standards Track + status + Draft + date + 2018-07-19 + description + + xmppId + urn:xmpp:sm:3 + + + xep + XEP-0199 + name + XMPP Ping + type + Standards Track + status + Final + date + 2009-06-03 + description + + xmppId + urn:xmpp:ping + + + xep + XEP-0200 + name + Stanza Encryption + type + Standards Track + status + Deferred + date + 2007-05-30 + description + + xmppId + http://www.xmpp.org/extensions/xep-0200.html* + + + xep + XEP-0201 + name + Best Practices for Message Threads + type + Informational + status + Active + date + 2010-11-29 + description + + xmppId + + + + xep + XEP-0202 + name + Entity Time + type + Standards Track + status + Final + date + 2009-09-11 + description + + xmppId + urn:xmpp:time + + + xep + XEP-0203 + name + Delayed Delivery + type + Standards Track + status + Final + date + 2009-09-15 + description + + xmppId + urn:xmpp:delay + + + xep + XEP-0204 + name + Collaborative Data Objects + type + Standards Track + status + Deferred + date + 2007-01-17 + description + + xmppId + http://www.xmpp.org/extensions/xep-0204.html* + + + xep + XEP-0205 + name + Best Practices to Discourage Denial of Service Attacks + type + Informational + status + Active + date + 2009-01-07 + description + + xmppId + + + + xep + XEP-0206 + name + XMPP Over BOSH + type + Standards Track + status + Draft + date + 2014-04-09 + description + + xmppId + + + + xep + XEP-0207 + name + XMPP Eventing via Pubsub + type + Humorous + status + Active + date + 2007-04-01 + description + + xmppId + + + + xep + XEP-0208 + name + Bootstrapping Implementation of Jingle + type + Informational + status + Retracted + date + 2009-01-06 + description + + xmppId + + + + xep + XEP-0209 + name + Metacontacts + type + Standards Track + status + Deferred + date + 2007-04-10 + description + + xmppId + + + + xep + XEP-0210 + name + Requirements for Encrypted Sessions + type + Standards Track + status + Deferred + date + 2007-05-30 + description + + xmppId + + + + xep + XEP-0211 + name + XMPP Basic Client 2008 + type + Standards Track + status + Obsolete + date + 2007-07-11 + description + + xmppId + + + + xep + XEP-0212 + name + XMPP Basic Server 2008 + type + Standards Track + status + Obsolete + date + 2007-07-11 + description + + xmppId + + + + xep + XEP-0213 + name + XMPP Intermediate IM Client 2008 + type + Standards Track + status + Obsolete + date + 2007-07-11 + description + + xmppId + + + + xep + XEP-0214 + name + File Repository and Sharing + type + Standards Track + status + Deferred + date + 2009-01-05 + description + + xmppId + + + + xep + XEP-0215 + name + External Service Discovery + type + Standards Track + status + Deferred + date + 2015-10-20 + description + + xmppId + urn:xmpp:extdisco:2 + + + xep + XEP-0216 + name + XMPP Intermediate IM Server 2008 + type + Standards Track + status + Obsolete + date + 2007-07-11 + description + + xmppId + + + + xep + XEP-0217 + name + Simplified Encrypted Session Negotiation + type + Standards Track + status + Deferred + date + 2007-05-30 + description + + xmppId + + + + xep + XEP-0218 + name + Bootstrapping Implementation of Encrypted Sessions + type + Informational + status + Deferred + date + 2007-05-30 + description + + xmppId + + + + xep + XEP-0219 + name + Hop Check + type + Standards Track + status + Retracted + date + 2008-06-12 + description + + xmppId + http://www.xmpp.org/extensions/xep-0219.html#ns + + + xep + XEP-0220 + name + Server Dialback + type + Standards Track + status + Draft + date + 2015-03-12 + description + + xmppId + + + + xep + XEP-0221 + name + Data Forms Media Element + type + Standards Track + status + Draft + date + 2008-09-03 + description + + xmppId + urn:xmpp:media-element + + + xep + XEP-0222 + name + Persistent Storage of Public Data via PubSub + type + Informational + status + Active + date + 2008-09-08 + description + + xmppId + + + + xep + XEP-0223 + name + Persistent Storage of Private Data via PubSub + type + Informational + status + Active + date + 2018-03-28 + description + + xmppId + + + + xep + XEP-0224 + name + Attention + type + Standards Track + status + Draft + date + 2008-11-13 + description + + xmppId + urn:xmpp:attention:0 + + + xep + XEP-0225 + name + Component Connections + type + Standards Track + status + Deferred + date + 2008-10-06 + description + + xmppId + urn:xmpp:component:0 + + + xep + XEP-0226 + name + Message Stanza Profiles + type + Informational + status + Deferred + date + 2008-11-05 + description + + xmppId + + + + xep + XEP-0227 + name + Portable Import/Export Format for XMPP-IM Servers + type + Standards Track + status + Draft + date + 2010-03-12 + description + + xmppId + + + + xep + XEP-0228 + name + Requirements for Shared Editing + type + Standards Track + status + Deferred + date + 2007-08-22 + description + + xmppId + + + + xep + XEP-0229 + name + Stream Compression with LZW + type + Standards Track + status + Draft + date + 2007-09-26 + description + + xmppId + + + + xep + XEP-0230 + name + Service Discovery Notifications + type + Standards Track + status + Deferred + date + 2016-10-04 + description + + xmppId + + + + xep + XEP-0231 + name + Bits of Binary + type + Standards Track + status + Draft + date + 2008-09-03 + description + + xmppId + urn:xmpp:bob + + + xep + XEP-0232 + name + Software Information + type + Standards Track + status + Deferred + date + 2009-02-26 + description + + xmppId + + + + xep + XEP-0233 + name + XMPP Server Registration for use with Kerberos V5 + type + Standards Track + status + Draft + date + 2017-03-16 + description + + xmppId + + + + xep + XEP-0234 + name + Jingle File Transfer + type + Standards Track + status + Proposed + date + 2017-08-24 + description + + xmppId + urn:xmpp:jingle:apps:file-transfer:5 + + + xep + XEP-0235 + name + OAuth Over XMPP + type + Standards Track + status + Deferred + date + 2009-03-24 + description + + xmppId + urn:xmpp:oauth:0 + + + xep + XEP-0236 + name + Abuse Reporting + type + Standards Track + status + Retracted + date + 2008-05-09 + description + + xmppId + urn:xmpp:tmp:abuse + + + xep + XEP-0237 + name + Roster Versioning + type + Standards Track + status + Obsolete + date + 2012-02-08 + description + + xmppId + urn:xmpp:features:rosterver + + + xep + XEP-0238 + name + XMPP Protocol Flows for Inter-Domain Federation + type + Informational + status + Deferred + date + 2008-03-31 + description + + xmppId + + + + xep + XEP-0239 + name + Binary XMPP + type + Humorous + status + Active + date + 2008-04-01 + description + + xmppId + + + + xep + XEP-0240 + name + Auto-Discovery of JabberIDs + type + Standards Track + status + Deferred + date + 2008-04-30 + description + + xmppId + + + + xep + XEP-0241 + name + Encryption of Archived Messages + type + Standards Track + status + Deferred + date + 2008-04-30 + description + + xmppId + urn:xmpp:tmp:archive:encrypt + + + xep + XEP-0242 + name + XMPP Client Compliance 2009 + type + Standards Track + status + Obsolete + date + 2008-09-08 + description + + xmppId + + + + xep + XEP-0243 + name + XMPP Server Compliance 2009 + type + Standards Track + status + Obsolete + date + 2008-09-08 + description + + xmppId + + + + xep + XEP-0244 + name + IO Data + type + Standards Track + status + Deferred + date + 2008-06-18 + description + + xmppId + urn:xmpp:tmp:io-data + + + xep + XEP-0245 + name + The /me Command + type + Informational + status + Active + date + 2009-01-21 + description + + xmppId + + + + xep + XEP-0246 + name + End-to-End XML Streams + type + Standards Track + status + Deferred + date + 2016-01-20 + description + + xmppId + + + + xep + XEP-0247 + name + Jingle XML Streams + type + Standards Track + status + Deferred + date + 2009-02-20 + description + + xmppId + + + + xep + XEP-0248 + name + PubSub Collection Nodes + type + Standards Track + status + Deferred + date + 2010-09-28 + description + + xmppId + http://jabber.org/protocol/pubsub#collections + + + xep + XEP-0249 + name + Direct MUC Invitations + type + Standards Track + status + Draft + date + 2011-09-22 + description + + xmppId + + + + xep + XEP-0250 + name + C2C Authentication Using TLS + type + Standards Track + status + Deferred + date + 2008-09-08 + description + + xmppId + + + + xep + XEP-0251 + name + Jingle Session Transfer + type + Standards Track + status + Deferred + date + 2009-10-05 + description + + xmppId + + + + xep + XEP-0252 + name + BOSH Script Syntax + type + Historical + status + Deferred + date + 2008-10-31 + description + + xmppId + + + + xep + XEP-0253 + name + PubSub Chaining + type + Standards Track + status + Deferred + date + 2009-11-18 + description + + xmppId + http://jabber.org/protocol/pubsub#chaining + + + xep + XEP-0254 + name + PubSub Queueing + type + Standards Track + status + Deferred + date + 2008-11-13 + description + + xmppId + urn:xmpp:pubsub:queueing:0 + + + xep + XEP-0255 + name + Location Query + type + Standards Track + status + Deferred + date + 2009-04-09 + description + + xmppId + urn:xmpp:locationquery:0 + + + xep + XEP-0256 + name + Last Activity in Presence + type + Standards Track + status + Draft + date + 2009-09-15 + description + + xmppId + jabber:iq:last + + + xep + XEP-0257 + name + Client Certificate Management for SASL EXTERNAL + type + Standards Track + status + Deferred + date + 2012-07-18 + description + + xmppId + urn:xmpp:saslcert:1 + + + xep + XEP-0258 + name + Security Labels in XMPP + type + Standards Track + status + Draft + date + 2013-04-08 + description + + xmppId + urn:xmpp:sec-label:0 + + + xep + XEP-0259 + name + Message Mine-ing + type + Standards Track + status + Deferred + date + 2009-01-21 + description + + xmppId + urn:xmpp:tmp:mine:0 + + + xep + XEP-0260 + name + Jingle SOCKS5 Bytestreams Transport Method + type + Standards Track + status + Draft + date + 2018-05-04 + description + + xmppId + urn:xmpp:jingle:transports:s5b:1 + + + xep + XEP-0261 + name + Jingle In-Band Bytestreams Transport Method + type + Standards Track + status + Draft + date + 2011-09-23 + description + + xmppId + urn:xmpp:jingle:transports:ibb:* + + + xep + XEP-0262 + name + Use of ZRTP in Jingle RTP Sessions + type + Standards Track + status + Draft + date + 2011-06-15 + description + + xmppId + urn:xmpp:jingle:apps:rtp:zrtp:* + + + xep + XEP-0263 + name + ECO-XMPP + type + Humorous + status + Active + date + 2009-04-01 + description + + xmppId + + + + xep + XEP-0264 + name + Jingle Content Thumbnails + type + Standards Track + status + Deferred + date + 2015-08-26 + description + + xmppId + urn:xmpp:thumbs:1 + + + xep + XEP-0265 + name + Out-of-Band Stream Data + type + Standards Track + status + Deferred + date + 2009-04-02 + description + + xmppId + urn:xmpp:jingle:apps:out-of-band:0 + + + xep + XEP-0266 + name + Codecs for Jingle Audio + type + Standards Track + status + Draft + date + 2013-03-01 + description + + xmppId + + + + xep + XEP-0267 + name + Server Buddies + type + Standards Track + status + Deferred + date + 2012-05-29 + description + + xmppId + urn:xmpp:server-presence + + + xep + XEP-0268 + name + Incident Handling + type + Standards Track + status + Deferred + date + 2012-05-29 + description + + xmppId + urn:xmpp:incident:2 + + + xep + XEP-0269 + name + Jingle Early Media + type + Standards Track + status + Deferred + date + 2009-05-19 + description + + xmppId + + + + xep + XEP-0270 + name + XMPP Compliance Suites 2010 + type + Standards Track + status + Obsolete + date + 2017-01-28 + description + + xmppId + + + + xep + XEP-0271 + name + XMPP Nodes + type + Informational + status + Deferred + date + 2009-06-26 + description + + xmppId + + + + xep + XEP-0272 + name + Multiparty Jingle (Muji) + type + Standards Track + status + Deferred + date + 2009-09-11 + description + + xmppId + http://telepathy.freedesktop.org/muji + + + xep + XEP-0273 + name + Stanza Interception and Filtering Technology (SIFT) + type + Standards Track + status + Deferred + date + 2011-06-27 + description + + xmppId + urn:xmpp:sift:* + + + xep + XEP-0274 + name + Design Considerations for Digital Signatures in XMPP + type + Informational + status + Deferred + date + 2011-01-28 + description + + xmppId + + + + xep + XEP-0275 + name + Entity Reputation + type + Standards Track + status + Deferred + date + 2012-06-06 + description + + xmppId + urn:xmpp:reputation:0 + + + xep + XEP-0276 + name + Presence Decloaking + type + Standards Track + status + Deferred + date + 2012-07-13 + description + + xmppId + urn:xmpp:decloak:0 + + + xep + XEP-0277 + name + Microblogging over XMPP + type + Standards Track + status + Deferred + date + 2017-11-28 + description + + xmppId + + + + xep + XEP-0278 + name + Jingle Relay Nodes + type + Standards Track + status + Experimental + date + 2017-09-14 + description + + xmppId + http://jabber.org/protocol/jinglenodes* + + + xep + XEP-0279 + name + Server IP Check + type + Standards Track + status + Deferred + date + 2013-04-17 + description + + xmppId + urn:xmpp:sic:1 + + + xep + XEP-0280 + name + Message Carbons + type + Standards Track + status + Proposed + date + 2017-02-16 + description + + xmppId + urn:xmpp:carbons:2 + + + xep + XEP-0281 + name + DMUC1: Distributed Multi-User Chat + type + Standards Track + status + Retracted + date + 2010-07-20 + description + + xmppId + + + + xep + XEP-0282 + name + DMUC2: Distributed MUC + type + Standards Track + status + Deferred + date + 2010-06-11 + description + + xmppId + + + + xep + XEP-0283 + name + Moved + type + Standards Track + status + Experimental + date + 2018-08-06 + description + + xmppId + urn:xmpp:moved:0 + + + xep + XEP-0284 + name + Shared XML Editing + type + Standards Track + status + Deferred + date + 2010-07-02 + description + + xmppId + urn:xmpp:sxe:0 + + + xep + XEP-0285 + name + Encapsulating Digital Signatures in XMPP + type + Standards Track + status + Deferred + date + 2011-01-12 + description + + xmppId + urn:xmpp:signed:0 + + + xep + XEP-0286 + name + Mobile Considerations on LTE Networks + type + Informational + status + Active + date + 2018-01-25 + description + + xmppId + + + + xep + XEP-0287 + name + Spim Markers and Reports + type + Standards Track + status + Deferred + date + 2010-10-03 + description + + xmppId + urn:xmpp:spim-report:0 + + + xep + XEP-0287 + name + Spim Markers and Reports + type + Standards Track + status + Deferred + date + 2010-10-04 + description + + xmppId + urn:xmpp:spim-marker:0 + + + xep + XEP-0288 + name + Bidirectional Server-to-Server Connections + type + Standards Track + status + Draft + date + 2016-10-17 + description + + xmppId + urn:xmpp:bidi + + + xep + XEP-0289 + name + Federated MUC for Constrained Environments + type + Standards Track + status + Deferred + date + 2012-05-29 + description + + xmppId + http://isode.com/protocol/fmuc + + + xep + XEP-0290 + name + Encapsulated Digital Signatures in XMPP + type + Standards Track + status + Deferred + date + 2011-01-28 + description + + xmppId + urn:xmpp:dsig:0 + + + xep + XEP-0291 + name + Service Delegation + type + Standards Track + status + Deferred + date + 2011-01-26 + description + + xmppId + urn:xmpp:tmp:delegate + + + xep + XEP-0292 + name + vCard4 Over XMPP + type + Standards Track + status + Deferred + date + 2013-09-12 + description + + xmppId + urn:ietf:params:xml:ns:vcard-4.0 + + + xep + XEP-0293 + name + Jingle RTP Feedback Negotiation + type + Standards Track + status + Draft + date + 2015-08-11 + description + + xmppId + urn:xmpp:jingle:apps:rtp:rtcp-fb:0 + + + xep + XEP-0294 + name + Jingle RTP Header Extensions Negotiation + type + Standards Track + status + Draft + date + 2015-08-11 + description + + xmppId + urn:xmpp:jingle:apps:rtp:rtp-hdrext:0 + + + xep + XEP-0295 + name + JSON Encodings for XMPP + type + Humorous + status + Active + date + 2011-04-01 + description + + xmppId + + + + xep + XEP-0296 + name + Best Practices for Resource Locking + type + Informational + status + Deferred + date + 2011-08-18 + description + + xmppId + + + + xep + XEP-0297 + name + Stanza Forwarding + type + Standards Track + status + Draft + date + 2013-10-02 + description + + xmppId + urn:xmpp:forward:0 + + + xep + XEP-0298 + name + Delivering Conference Information to Jingle Participants (Coin) + type + Standards Track + status + Deferred + date + 2015-07-02 + description + + xmppId + urn:xmpp:coin:1 + + + xep + XEP-0299 + name + Codecs for Jingle Video + type + Standards Track + status + Deferred + date + 2011-06-12 + description + + xmppId + + + + xep + XEP-0300 + name + Use of Cryptographic Hash Functions in XMPP + type + Standards Track + status + Experimental + date + 2018-02-14 + description + + xmppId + urn:xmpp:hashes:2 + + + xep + XEP-0301 + name + In-Band Real Time Text + type + Standards Track + status + Draft + date + 2013-10-08 + description + + xmppId + urn:xmpp:rtt:0 + + + xep + XEP-0302 + name + XMPP Compliance Suites 2012 + type + Standards Track + status + Obsolete + date + 2011-07-21 + description + + xmppId + + + + xep + XEP-0303 + name + Commenting + type + Standards Track + status + Deferred + date + 2011-07-28 + description + + xmppId + urn:xmpp:tmp:comments:0 + + + xep + XEP-0304 + name + Whitespace Keepalive Negotiation + type + Standards Track + status + Deferred + date + 2011-08-18 + description + + xmppId + urn:xmpp:keepalive:0 + + + xep + XEP-0305 + name + XMPP Quickstart + type + Standards Track + status + Deferred + date + 2013-03-01 + description + + xmppId + + + + xep + XEP-0306 + name + Extensible Status Conditions for Multi-User Chat + type + Standards Track + status + Deferred + date + 2016-06-07 + description + + xmppId + urn:xmpp:muc:conditions:1 + + + xep + XEP-0307 + name + Unique Room Names for Multi-User Chat + type + Standards Track + status + Deferred + date + 2011-11-10 + description + + xmppId + http://jabber.org/protocol/muc#unique + + + xep + XEP-0308 + name + Last Message Correction + type + Standards Track + status + Draft + date + 2013-04-08 + description + + xmppId + urn:xmpp:message-correct:0 + + + xep + XEP-0309 + name + Service Directories + type + Standards Track + status + Deferred + date + 2012-05-29 + description + + xmppId + urn:xmpp:public-server + + + xep + XEP-0310 + name + Presence State Annotations + type + Standards Track + status + Deferred + date + 2012-01-10 + description + + xmppId + urn:xmpp:psa + + + xep + XEP-0311 + name + MUC Fast Reconnect + type + Standards Track + status + Deferred + date + 2012-01-25 + description + + xmppId + urn:xmpp:presence-session:0 + + + xep + XEP-0312 + name + PubSub Since + type + Standards Track + status + Deferred + date + 2012-05-29 + description + + xmppId + http://jabber.org/protocol/pubsub#since + + + xep + XEP-0313 + name + Message Archive Management + type + Standards Track + status + Experimental + date + 2018-07-16 + description + + xmppId + urn:xmpp:mam:2 + + + xep + XEP-0314 + name + Security Labels in PubSub + type + Standards Track + status + Deferred + date + 2012-07-27 + description + + xmppId + + + + xep + XEP-0315 + name + Data Forms XML Element + type + Standards Track + status + Deferred + date + 2012-10-15 + description + + xmppId + + + + xep + XEP-0316 + name + MUC Eventing Protocol + type + Standards Track + status + Deferred + date + 2013-01-03 + description + + xmppId + + + + xep + XEP-0317 + name + Hats + type + Standards Track + status + Deferred + date + 2013-01-03 + description + + xmppId + + + + xep + XEP-0318 + name + Best Practices for Client Initiated Presence Probes + type + Informational + status + Deferred + date + 2013-08-06 + description + + xmppId + + + + xep + XEP-0319 + name + Last User Interaction in Presence + type + Standards Track + status + Draft + date + 2017-07-17 + description + + xmppId + urn:xmpp:idle:1 + + + xep + XEP-0320 + name + Use of DTLS-SRTP in Jingle Sessions + type + Standards Track + status + Deferred + date + 2015-10-15 + description + + xmppId + urn:xmpp:jingle:apps:dtls:0 + + + xep + XEP-0321 + name + Remote Roster Management + type + Standards Track + status + Deferred + date + 2013-04-16 + description + + xmppId + urn:xmpp:tmp:roster-management:0 + + + xep + XEP-0322 + name + Efficient XML Interchange (EXI) Format + type + Standards Track + status + Deferred + date + 2018-01-25 + description + + xmppId + + + + xep + XEP-0323 + name + Internet of Things - Sensor Data + type + Standards Track + status + Retracted + date + 2017-05-20 + description + + xmppId + urn:xmpp:iot:sensordata + + + xep + XEP-0324 + name + Internet of Things - Provisioning + type + Standards Track + status + Retracted + date + 2017-05-20 + description + + xmppId + urn:xmpp:iot:provisioning + + + xep + XEP-0325 + name + Internet of Things - Control + type + Standards Track + status + Retracted + date + 2017-05-20 + description + + xmppId + urn:xmpp:iot:control + + + xep + XEP-0326 + name + Internet of Things - Concentrators + type + Standards Track + status + Retracted + date + 2017-05-20 + description + + xmppId + urn:xmpp:iot:concentrators + + + xep + XEP-0327 + name + Rayo + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:rayo:1 + + + xep + XEP-0328 + name + JID Prep + type + Standards Track + status + Deferred + date + 2013-05-28 + description + + xmppId + urn:xmpp:jidprep:0 + + + xep + XEP-0329 + name + File Information Sharing + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:fis:0 + + + xep + XEP-0330 + name + Pubsub Subscription + type + Standards Track + status + Deferred + date + 2013-06-11 + description + + xmppId + + + + xep + XEP-0331 + name + Data Forms - Color Field Types + type + Standards Track + status + Deferred + date + 2015-11-09 + description + + xmppId + + + + xep + XEP-0332 + name + HTTP over XMPP transport + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:http + + + xep + XEP-0333 + name + Chat Markers + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:chat-markers:0 + + + xep + XEP-0334 + name + Message Processing Hints + type + Standards Track + status + Deferred + date + 2018-01-25 + description + + xmppId + urn:xmpp:hints + + + xep + XEP-0335 + name + JSON Containers + type + Standards Track + status + Deferred + date + 2013-10-25 + description + + xmppId + urn:xmpp:json:0 + + + xep + XEP-0336 + name + Data Forms - Dynamic Forms + type + Standards Track + status + Deferred + date + 2015-11-09 + description + + xmppId + urn:xmpp:xdata:dynamic + + + xep + XEP-0337 + name + Event Logging over XMPP + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:eventlog + + + xep + XEP-0338 + name + Jingle Grouping Framework + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:ietf:rfc:5888 + + + xep + XEP-0339 + name + Source-Specific Media Attributes in Jingle + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:ietf:rfc:5576 + + + xep + XEP-0340 + name + COnferences with LIghtweight BRIdging (COLIBRI) + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + http://jitsi.org/protocol/colibri + + + xep + XEP-0341 + name + Rayo CPA + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:rayo:cpa:0 + + + xep + XEP-0342 + name + Rayo Fax + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:rayo:fax:1 + + + xep + XEP-0343 + name + Signaling WebRTC datachannels in Jingle + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0344 + name + Impact of TLS and DNSSEC on Dialback + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0345 + name + Form of Membership Applications + type + Procedural + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0346 + name + Form Discovery and Publishing + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0347 + name + Internet of Things - Discovery + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:iot:discovery + + + xep + XEP-0348 + name + Signing Forms + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:xdata:signature:oauth1 + + + xep + XEP-0349 + name + Rayo Clustering + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0350 + name + Data Forms Geolocation Element + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0351 + name + Recipient Server Side Notifications Filtering + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0352 + name + Client State Indication + type + Standards Track + status + Proposed + date + 2017-02-18 + description + + xmppId + urn:xmpp:csi:0 + + + xep + XEP-0353 + name + Jingle Message Initiation + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0354 + name + Customizable Message Routing + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:cmr:0 + + + xep + XEP-0355 + name + Namespace Delegation + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:delegation:1 + + + xep + XEP-0356 + name + Privileged Entity + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:privilege:1 + + + xep + XEP-0357 + name + Push Notifications + type + Standards Track + status + Experimental + date + 2017-08-24 + description + + xmppId + urn:xmpp:push:0 + + + xep + XEP-0358 + name + Publishing Available Jingle Sessions + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0359 + name + Unique and Stable Stanza IDs + type + Standards Track + status + Experimental + date + 2017-08-23 + description + + xmppId + urn:xmpp:sid:0 + + + xep + XEP-0360 + name + Nonzas (are not Stanzas) + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0361 + name + Zero Handshake Server to Server Protocol + type + Informational + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0362 + name + Raft over XMPP + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:raft + + + xep + XEP-0363 + name + HTTP File Upload + type + Standards Track + status + Proposed + date + 2018-05-30 + description + + xmppId + urn:xmpp:http:upload:0 + + + xep + XEP-0364 + name + Current Off-the-Record Messaging Usage + type + Informational + status + Deferred + date + 2017-01-28 + description + + xmppId + + + + xep + XEP-0365 + name + Server to Server communication over STANAG 5066 ARQ + type + Standards Track + status + Deferred + date + 2018-07-21 + description + + xmppId + + + + xep + XEP-0366 + name + Entity Versioning + type + Standards Track + status + Deferred + date + 2016-12-21 + description + + xmppId + urn:xmpp:entityver:0 + + + xep + XEP-0367 + name + Message Attaching + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:message-attaching:0 + + + xep + XEP-0368 + name + SRV records for XMPP over TLS + type + Standards Track + status + Draft + date + 2017-03-09 + description + + xmppId + + + + xep + XEP-0369 + name + Mediated Information eXchange (MIX) + type + Standards Track + status + Experimental + date + 2018-06-06 + description + + xmppId + urn:xmpp:mix:core:* + + + xep + XEP-0370 + name + Jingle HTTP Transport Method + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0371 + name + Jingle ICE Transport Method + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0372 + name + References + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:reference:0 + + + xep + XEP-0373 + name + OpenPGP for XMPP + type + Standards Track + status + Experimental + date + 2018-07-30 + description + + xmppId + + + + xep + XEP-0374 + name + OpenPGP for XMPP Instant Messaging + type + Standards Track + status + Deferred + date + 2018-01-25 + description + + xmppId + urn:xmpp:openpgp:im:0 + + + xep + XEP-0375 + name + XMPP Compliance Suites 2016 + type + Standards Track + status + Retracted + date + 2016-07-20 + description + + xmppId + + + + xep + XEP-0376 + name + Pubsub Account Management + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + + + + xep + XEP-0377 + name + Spam Reporting + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:reporting:* + + + xep + XEP-0378 + name + OTR Discovery + type + Standards Track + status + Deferred + date + 2017-09-11 + description + + xmppId + urn:xmpp:otr:0 + + + xep + XEP-0379 + name + Pre-Authenticated Roster Subscription + type + Standards Track + status + Experimental + date + 2017-03-06 + description + + xmppId + + + + xep + XEP-0380 + name + Explicit Message Encryption + type + Standards Track + status + Deferred + date + 2018-01-25 + description + + xmppId + urn:xmpp:eme:0 + + + xep + XEP-0381 + name + Internet of Things Special Interest Group (IoT SIG) + type + Procedural + status + Proposed + date + 2016-11-23 + description + + xmppId + + + + xep + XEP-0382 + name + Spoiler messages + type + Standards Track + status + Deferred + date + 2018-01-25 + description + + xmppId + urn:xmpp:spoiler:0 + + + xep + XEP-0383 + name + Burner JIDs + type + Standards Track + status + Deferred + date + 2017-01-28 + description + + xmppId + urn:xmpp:burner:0 + + + xep + XEP-0384 + name + OMEMO Encryption + type + Standards Track + status + Experimental + date + 2018-05-21 + description + + xmppId + eu.siacs.conversations.axolotl + + + xep + XEP-0385 + name + Stateless Inline Media Sharing (SIMS) + type + Standards Track + status + Experimental + date + 2018-01-25 + description + + xmppId + urn:xmpp:sims:1 + + + xep + XEP-0386 + name + Bind 2.0 + type + Standards Track + status + Deferred + date + 2018-02-08 + description + + xmppId + urn:xmpp:bind2:0 + + + xep + XEP-0387 + name + XMPP Compliance Suites 2018 + type + Standards Track + status + Draft + date + 2018-01-25 + description + + xmppId + + + + xep + XEP-0388 + name + Extensible SASL Profile + type + Standards Track + status + Experimental + date + 2017-08-24 + description + + xmppId + + + + xep + XEP-0389 + name + Extensible In-Band Registration + type + Standards Track + status + Experimental + date + 2017-03-16 + description + + xmppId + + + + xep + XEP-0390 + name + Entity Capabilities 2.0 + type + Standards Track + status + Experimental + date + 2017-06-14 + description + + xmppId + urn:xmpp:caps + + + xep + XEP-0391 + name + Jingle Encrypted Transports + type + Standards Track + status + Experimental + date + 2018-07-31 + description + + xmppId + urn:xmpp:jingle:jet:0 + + + xep + XEP-0392 + name + Consistent Color Generation + type + Standards Track + status + Experimental + date + 2018-07-28 + description + + xmppId + + + + xep + XEP-0393 + name + Message Styling + type + Standards Track + status + Experimental + date + 2018-05-01 + description + + xmppId + + + + xep + XEP-0394 + name + Message Markup + type + Standards Track + status + Experimental + date + 2017-11-22 + description + + xmppId + urn:xmpp:markup:0 + + + xep + XEP-0395 + name + Atomically Compare-And-Publish PubSub Items + type + Standards Track + status + Experimental + date + 2017-11-29 + description + + xmppId + + + + xep + XEP-0396 + name + Jingle Encrypted Transports - OMEMO + type + Standards Track + status + Experimental + date + 2017-11-29 + description + + xmppId + urn:xmpp:jingle:jet-omemo:0 + + + xep + XEP-0397 + name + Instant Stream Resumption + type + Standards Track + status + Experimental + date + 2018-01-22 + description + + xmppId + https://xmpp.org/extensions/isr/0 + + + xep + XEP-0398 + name + User Avatar to vCard-Based Avatars Conversion + type + Standards Track + status + Experimental + date + 2018-08-27 + description + + xmppId + urn:xmpp:pep-vcard-conversion:0 + + + xep + XEP-0399 + name + Client Key Support + type + Standards Track + status + Experimental + date + 2018-01-25 + description + + xmppId + urn:xmpp:client-key:0 + + + xep + XEP-0400 + name + Multi-Factor Authentication with TOTP + type + Standards Track + status + Experimental + date + 2018-01-25 + description + + xmppId + urn:xmpp:mfa:0 + + + xep + XEP-0401 + name + Easy User Onboarding + type + Standards Track + status + Experimental + date + 2018-02-11 + description + + xmppId + + + + xep + XEP-0402 + name + Bookmarks 2 (This Time it's Serious) + type + Standards Track + status + Experimental + date + 2018-07-22 + description + + xmppId + urn:xmpp:bookmarks:0 + + + xep + XEP-0403 + name + Mediated Information eXchange (MIX): Presence Support. + type + Standards Track + status + Experimental + date + 2018-06-06 + description + + xmppId + urn:xmpp:mix:nodes:presence + + + xep + XEP-0404 + name + Mediated Information eXchange (MIX): JID Hidden Channels. + type + Standards Track + status + Experimental + date + 2018-06-06 + description + + xmppId + + + + xep + XEP-0405 + name + Mediated Information eXchange (MIX): Participant Server Requirements + type + Standards Track + status + Experimental + date + 2018-06-06 + description + + xmppId + urn:xmpp:mix:pam:0 + + + xep + XEP-0406 + name + Mediated Information eXchange (MIX): MIX Administration + type + Standards Track + status + Experimental + date + 2018-06-06 + description + + xmppId + + + + xep + XEP-0407 + name + Mediated Information eXchange (MIX): Miscellaneous Capabilities + type + Standards Track + status + Experimental + date + 2018-05-14 + description + + xmppId + urn:xmpp:mix:misc:* + + + xep + XEP-0408 + name + Mediated Information eXchange (MIX): Co-existence with MUC + type + Standards Track + status + Experimental + date + 2018-05-21 + description + + xmppId + + + + xep + XEP-0409 + name + IM Routing-NG + type + Standards Track + status + Experimental + date + 2018-06-05 + description + + xmppId + urn:xmpp:im-ng:0 + + + xep + XEP-0410 + name + MUC Self-Ping (Schrödinger's Chat) + type + Standards Track + status + Experimental + date + 2018-08-31 + description + + xmppId + + + + diff --git a/ConversationsClassic/View/BaseNavigationView.swift b/old/View/BaseNavigationView.swift similarity index 100% rename from ConversationsClassic/View/BaseNavigationView.swift rename to old/View/BaseNavigationView.swift diff --git a/ConversationsClassic/View/Screens/AddAccountScreen.swift b/old/View/Screens/AddAccountScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/AddAccountScreen.swift rename to old/View/Screens/AddAccountScreen.swift diff --git a/ConversationsClassic/View/Screens/Chats/ChatsCreateMainScreen.swift b/old/View/Screens/Chats/ChatsCreateMainScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/Chats/ChatsCreateMainScreen.swift rename to old/View/Screens/Chats/ChatsCreateMainScreen.swift diff --git a/ConversationsClassic/View/Screens/Chats/ChatsListScreen.swift b/old/View/Screens/Chats/ChatsListScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/Chats/ChatsListScreen.swift rename to old/View/Screens/Chats/ChatsListScreen.swift diff --git a/ConversationsClassic/View/Screens/Contacts/AddContactOrChannelScreen.swift b/old/View/Screens/Contacts/AddContactOrChannelScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/Contacts/AddContactOrChannelScreen.swift rename to old/View/Screens/Contacts/AddContactOrChannelScreen.swift diff --git a/ConversationsClassic/View/Screens/Contacts/ContactsScreen.swift b/old/View/Screens/Contacts/ContactsScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/Contacts/ContactsScreen.swift rename to old/View/Screens/Contacts/ContactsScreen.swift diff --git a/ConversationsClassic/View/Screens/Conversation/ConversationMessageContainer.swift b/old/View/Screens/Conversation/ConversationMessageContainer.swift similarity index 100% rename from ConversationsClassic/View/Screens/Conversation/ConversationMessageContainer.swift rename to old/View/Screens/Conversation/ConversationMessageContainer.swift diff --git a/ConversationsClassic/View/Screens/Conversation/ConversationMessageRow.swift b/old/View/Screens/Conversation/ConversationMessageRow.swift similarity index 100% rename from ConversationsClassic/View/Screens/Conversation/ConversationMessageRow.swift rename to old/View/Screens/Conversation/ConversationMessageRow.swift diff --git a/ConversationsClassic/View/Screens/Conversation/ConversationScreen.swift b/old/View/Screens/Conversation/ConversationScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/Conversation/ConversationScreen.swift rename to old/View/Screens/Conversation/ConversationScreen.swift diff --git a/ConversationsClassic/View/Screens/Conversation/ConversationTextInput.swift b/old/View/Screens/Conversation/ConversationTextInput.swift similarity index 100% rename from ConversationsClassic/View/Screens/Conversation/ConversationTextInput.swift rename to old/View/Screens/Conversation/ConversationTextInput.swift diff --git a/ConversationsClassic/View/Screens/RegistrationScreen.swift b/old/View/Screens/RegistrationScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/RegistrationScreen.swift rename to old/View/Screens/RegistrationScreen.swift diff --git a/ConversationsClassic/View/Screens/Settings/SettingsScreen.swift b/old/View/Screens/Settings/SettingsScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/Settings/SettingsScreen.swift rename to old/View/Screens/Settings/SettingsScreen.swift diff --git a/ConversationsClassic/View/Screens/Sharing/SharingContactsPickerView.swift b/old/View/Screens/Sharing/SharingContactsPickerView.swift similarity index 100% rename from ConversationsClassic/View/Screens/Sharing/SharingContactsPickerView.swift rename to old/View/Screens/Sharing/SharingContactsPickerView.swift diff --git a/ConversationsClassic/View/Screens/Sharing/SharingFilesPickerView.swift b/old/View/Screens/Sharing/SharingFilesPickerView.swift similarity index 100% rename from ConversationsClassic/View/Screens/Sharing/SharingFilesPickerView.swift rename to old/View/Screens/Sharing/SharingFilesPickerView.swift diff --git a/ConversationsClassic/View/Screens/Sharing/SharingLocationPickerView.swift b/old/View/Screens/Sharing/SharingLocationPickerView.swift similarity index 100% rename from ConversationsClassic/View/Screens/Sharing/SharingLocationPickerView.swift rename to old/View/Screens/Sharing/SharingLocationPickerView.swift diff --git a/ConversationsClassic/View/Screens/Sharing/SharingMediaPickerView.swift b/old/View/Screens/Sharing/SharingMediaPickerView.swift similarity index 100% rename from ConversationsClassic/View/Screens/Sharing/SharingMediaPickerView.swift rename to old/View/Screens/Sharing/SharingMediaPickerView.swift diff --git a/ConversationsClassic/View/Screens/Sharing/SharingPickerScreen.swift b/old/View/Screens/Sharing/SharingPickerScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/Sharing/SharingPickerScreen.swift rename to old/View/Screens/Sharing/SharingPickerScreen.swift diff --git a/ConversationsClassic/View/Screens/Sharing/SharingTabBar.swift b/old/View/Screens/Sharing/SharingTabBar.swift similarity index 100% rename from ConversationsClassic/View/Screens/Sharing/SharingTabBar.swift rename to old/View/Screens/Sharing/SharingTabBar.swift diff --git a/ConversationsClassic/View/Screens/StartScreen.swift b/old/View/Screens/StartScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/StartScreen.swift rename to old/View/Screens/StartScreen.swift diff --git a/ConversationsClassic/View/Screens/WelcomeScreen.swift b/old/View/Screens/WelcomeScreen.swift similarity index 100% rename from ConversationsClassic/View/Screens/WelcomeScreen.swift rename to old/View/Screens/WelcomeScreen.swift diff --git a/old/View/SharedComponents/SharedListRow.swift b/old/View/SharedComponents/SharedListRow.swift new file mode 100644 index 0000000..7e5fa74 --- /dev/null +++ b/old/View/SharedComponents/SharedListRow.swift @@ -0,0 +1,59 @@ +import SwiftUI + +enum SharedListRowIconType { + case charCircle(String) + case image(Image, Color) +} + +struct SharedListRow: View { + let iconType: SharedListRowIconType + let text: String + + var body: some View { + VStack(spacing: 0) { + HStack(spacing: 8) { + // Icon + switch iconType { + case .charCircle(let str): + let char = str.firstLetter + let color = str.firstLetterColor + ZStack { + Circle() + .frame(width: 44, height: 44) + .foregroundColor(color) + Text(char) + .foregroundColor(.white) + .font(.body1) + } + + case .image(let image, let color): + ZStack { + Circle() + .frame(width: 44, height: 44) + .foregroundColor(.clearTappable) + .overlay { + image + .foregroundColor(color) + } + } + } + + // Text + Text(text) + .foregroundColor(Color.Material.Text.main) + .font(.body2) + Spacer() + } + .padding(.horizontal, 16) + .padding(.vertical, 4) + Rectangle() + .frame(maxWidth: .infinity) + .frame(height: 1) + .foregroundColor(.Material.Background.dark) + } + .listRowInsets(.zero) + .listRowSeparator(.hidden) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color.Material.Background.light) + } +} diff --git a/old/View/SharedComponents/SharedNavigationBar.swift b/old/View/SharedComponents/SharedNavigationBar.swift new file mode 100644 index 0000000..f6e651a --- /dev/null +++ b/old/View/SharedComponents/SharedNavigationBar.swift @@ -0,0 +1,78 @@ +import SwiftUI + +struct SharedNavBarButton: View { + let image: Image? + let action: () -> Void + var isEnabled: Bool = true + + init( + image: Image, + action: @escaping () -> Void, + isEnabled: Bool = true + ) { + self.image = image + self.action = action + self.isEnabled = isEnabled + } + + var body: some View { + Button { + action() + } label: { + image + .foregroundColor(isEnabled ? .Material.Elements.active : .Material.Elements.inactive) + .tappablePadding(.symmetric(12)) { + action() + } + } + .disabled(!isEnabled) + } +} + +struct SharedNavBarText: View { + let text: String + + var body: some View { + Text(text) + .font(.head2) + .foregroundColor(.Material.Text.main) + } +} + +struct SharedNavigationBar: View { + var leftButton: SharedNavBarButton? + var centerText: SharedNavBarText? + var rightButton: SharedNavBarButton? + + var body: some View { + ZStack { + Color.Material.Background.dark + .ignoresSafeArea() + + VStack { + if centerText != nil { + centerText + } + } + Spacer() + + HStack(alignment: .center) { + VStack { + if leftButton != nil { + leftButton?.padding() + } + } + .frame(minWidth: 40) + Spacer() + VStack { + if rightButton != nil { + rightButton? + .padding() + } + } + .frame(minWidth: 40) + } + } + .frame(height: 44) + } +} diff --git a/old/View/SharedComponents/SharedTabBar.swift b/old/View/SharedComponents/SharedTabBar.swift new file mode 100644 index 0000000..8ca982c --- /dev/null +++ b/old/View/SharedComponents/SharedTabBar.swift @@ -0,0 +1,76 @@ +import SwiftUI + +struct SharedTabBar: View { + var body: some View { + VStack(spacing: 0) { + Rectangle() + .frame(maxWidth: .infinity) + .frame(height: 0.2) + .foregroundColor(.Material.Shape.separator) + HStack(spacing: 0) { + SharedTabBarButton(buttonFlow: .contacts) + SharedTabBarButton(buttonFlow: .chats) + SharedTabBarButton(buttonFlow: .settings) + } + .background(Color.Material.Background.dark) + } + .frame(height: 50) + } +} + +private struct SharedTabBarButton: View { + @EnvironmentObject var store: AppStore + + let buttonFlow: AppFlow + + var body: some View { + ZStack { + VStack(spacing: 2) { + buttonImg + .foregroundColor(buttonFlow == store.state.currentFlow ? .Material.Elements.active : .Material.Elements.inactive) + .font(.system(size: 24, weight: .light)) + .symbolRenderingMode(.hierarchical) + Text(buttonTitle) + .font(.sub1) + .foregroundColor(buttonFlow == store.state.currentFlow ? .Material.Text.main : .Material.Elements.inactive) + } + Rectangle() + .foregroundColor(.white.opacity(0.01)) + .onTapGesture { + store.dispatch(.changeFlow(buttonFlow)) + } + } + } + + var buttonImg: Image { + switch buttonFlow { + case .contacts: + return Image(systemName: "person.2.fill") + + case .chats: + return Image(systemName: "bubble.left.fill") + + case .settings: + return Image(systemName: "gearshape.fill") + + default: + return Image(systemName: "questionmark.circle") + } + } + + var buttonTitle: String { + switch buttonFlow { + case .contacts: + return "Contacts" + + case .chats: + return "Chats" + + case .settings: + return "Settings" + + default: + return "Unknown" + } + } +} diff --git a/old/View/SharedComponents/UniversalInputCollection.swift b/old/View/SharedComponents/UniversalInputCollection.swift new file mode 100644 index 0000000..fb8b5f8 --- /dev/null +++ b/old/View/SharedComponents/UniversalInputCollection.swift @@ -0,0 +1,203 @@ +import SwiftUI + +// MARK: Public +protocol UniversalInputSelectionElement: Identifiable, Equatable, Hashable { + var icon: Image? { get } + var text: String? { get } +} + +public enum UniversalInputCollection { + struct TextField { + let prompt: String + @Binding var text: String + var focus: FocusState.Binding + var fieldType: T + let contentType: UITextContentType + let keyboardType: UIKeyboardType + let submitLabel: SubmitLabel + let action: () -> Void + } + + struct SecureField { + let prompt: String + @Binding var text: String + var focus: FocusState.Binding + var fieldType: T + let submitLabel: SubmitLabel + let action: () -> Void + } + + struct DropDownMenu { + let prompt: String + let elements: [E] + @Binding var selected: E? + var focus: FocusState.Binding + var fieldType: T + } +} + +// MARK: Inputs implementations +extension UniversalInputCollection.TextField: View { + var body: some View { + TextField("", text: $text) + .padding(.horizontal, 8) + .focused(focus, equals: fieldType) + .font(.body2) + .foregroundColor(.Material.Text.main) + .autocorrectionDisabled(true) + .autocapitalization(.none) + .textContentType(contentType) + .keyboardType(keyboardType) + .submitLabel(submitLabel) + .textSelection(.enabled) + .onSubmit { + action() + } + .modifier(UniversalInputModifier( + prompt: prompt, + focus: focus, + fieldType: fieldType, + isActive: isFilled + )) + } + + var isFilled: Bool { + !text.isEmpty || focus.wrappedValue == fieldType + } +} + +extension UniversalInputCollection.SecureField: View { + var body: some View { + SecureField("", text: $text) + .padding(.horizontal, 8) + .focused(focus, equals: fieldType) + .font(.body2) + .foregroundColor(.Material.Text.main) + .autocorrectionDisabled(true) + .autocapitalization(.none) + .textContentType(.password) + .submitLabel(submitLabel) + .textSelection(.disabled) + .onSubmit { + action() + } + .modifier(UniversalInputModifier( + prompt: prompt, + focus: focus, + fieldType: fieldType, + isActive: isFilled + )) + } + + var isFilled: Bool { + !text.isEmpty || focus.wrappedValue == fieldType + } +} + +extension UniversalInputCollection.DropDownMenu: View { + var body: some View { + ZStack { + HStack { + Text(text) + .font(.body2) + .foregroundColor(.Material.Text.main) + .padding(.leading, 8) + Spacer() + } + .modifier(UniversalInputModifier( + prompt: prompt, + focus: focus, + fieldType: fieldType, + isActive: selected != nil + )) + + Menu { + ForEach(elements, id: \.self.id) { element in + Button { + selected = element + } label: { + Text(element.text ?? "") + } + } + } label: { + Label("", image: "") + .labelStyle(TitleOnlyLabelStyle()) + .padding(.vertical) + .frame(height: 48) + .frame(maxWidth: .infinity) + } + } + } + + var text: String { + if let text = selected?.text { + return text + } else { + return "" + } + } +} + +// MARK: Modifiers +private struct UniversalInputModifier: ViewModifier { + let prompt: String + var focus: FocusState.Binding + var fieldType: T + let isActive: Bool + var promptBackground: Color? + var isCentered: Bool? + var customTapAction: (() -> Void)? + + func body(content: Content) -> some View { + VStack(spacing: 0) { + ZStack { + HStack { + Text(isActive ? "" : prompt) + .font(.body2) + .foregroundColor(.Material.Shape.separator) + .padding(8) + Spacer() + } + content + .frame(height: 48) + } + } + .frame(height: 48) + .background { + ZStack { + RoundedRectangle(cornerRadius: 4) + .foregroundColor(.Material.Shape.white) + RoundedRectangle(cornerRadius: 4) + .stroke(Color.Material.Shape.separator) + } + } + .contentShape(Rectangle()) + .onTapGesture { + if let customTapAction { + customTapAction() + } else { + if focus.wrappedValue != fieldType { + focus.wrappedValue = fieldType + } + } + } + } +} + +// MARK: Validators +extension UniversalInputCollection { + enum Validators { + static func isEmail(_ input: String) -> Bool { + if !input.isEmpty { + let mailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}" + if !NSPredicate(format: "SELF MATCHES %@", mailRegex).evaluate(with: input) { + return false + } else { + return true + } + } else { + return true + } + } + } +} diff --git a/old/View/UIToolkit/Binding+Extensions.swift b/old/View/UIToolkit/Binding+Extensions.swift new file mode 100644 index 0000000..6a2a796 --- /dev/null +++ b/old/View/UIToolkit/Binding+Extensions.swift @@ -0,0 +1,12 @@ +import SwiftUI + +extension Binding where Value == String { + func max(_ limit: Int) -> Self { + if wrappedValue.count > limit { + DispatchQueue.main.async { + wrappedValue = String(wrappedValue.dropLast()) + } + } + return self + } +} diff --git a/old/View/UIToolkit/ButtonStyles.swift b/old/View/UIToolkit/ButtonStyles.swift new file mode 100644 index 0000000..62c59ab --- /dev/null +++ b/old/View/UIToolkit/ButtonStyles.swift @@ -0,0 +1,50 @@ +import SwiftUI + +private enum ButtonSizes { + static let padding = 16.0 + static let cornerRadius = 4.0 + static let scaleEffect: CGFloat = 0.9 + static let opacity: Double = 0.6 +} + +struct PrimaryButtonStyle: ButtonStyle { + @Environment(\.isEnabled) private var isEnabled + + func makeBody(configuration: Configuration) -> some View { + configuration + .label + .font(.head2) + .padding(ButtonSizes.padding) + .frame(maxWidth: .infinity) + .foregroundColor(.Material.Shape.white) + .background { + RoundedRectangle(cornerRadius: ButtonSizes.cornerRadius) + .foregroundColor(isEnabled ? .Material.Elements.active : .Material.Shape.separator) + } + .contentShape(Rectangle()) + .scaleEffect(configuration.isPressed ? ButtonSizes.scaleEffect : 1.0) + .opacity(configuration.isPressed ? ButtonSizes.opacity : 1.0) + .animation(.easeInOut(duration: 0.1), value: configuration.isPressed) + } +} + +struct SecondaryButtonStyle: ButtonStyle { + @Environment(\.isEnabled) private var isEnabled + + func makeBody(configuration: Configuration) -> some View { + configuration + .label + .font(.head2) + .padding(ButtonSizes.padding) + .frame(maxWidth: .infinity) + .foregroundColor(isEnabled ? .Material.Elements.active : .Material.Shape.separator) + .background { + RoundedRectangle(cornerRadius: ButtonSizes.cornerRadius) + .stroke(isEnabled ? Color.Material.Elements.active : Color.Material.Shape.separator) + } + .contentShape(Rectangle()) + .scaleEffect(configuration.isPressed ? ButtonSizes.scaleEffect : 1.0) + .opacity(configuration.isPressed ? ButtonSizes.opacity : 1.0) + .animation(.easeInOut(duration: 0.1), value: configuration.isPressed) + } +} diff --git a/old/View/UIToolkit/Colors+Tappable.swift b/old/View/UIToolkit/Colors+Tappable.swift new file mode 100644 index 0000000..718a3df --- /dev/null +++ b/old/View/UIToolkit/Colors+Tappable.swift @@ -0,0 +1,13 @@ +import SwiftUI + +public extension Color { + static let clearTappable = Color.white.opacity(0.0001) + // static func random(randomOpacity: Bool = false) -> Color { + // Color( + // red: .random(in: 0 ... 1), + // green: .random(in: 0 ... 1), + // blue: .random(in: 0 ... 1), + // opacity: randomOpacity ? .random(in: 0 ... 1) : 1 + // ) + // } +} diff --git a/old/View/UIToolkit/EdgeInsets+Extensions.swift b/old/View/UIToolkit/EdgeInsets+Extensions.swift new file mode 100644 index 0000000..65f5311 --- /dev/null +++ b/old/View/UIToolkit/EdgeInsets+Extensions.swift @@ -0,0 +1,15 @@ +import SwiftUI + +extension EdgeInsets { + var inverted: EdgeInsets { + .init(top: -top, leading: -leading, bottom: -bottom, trailing: -trailing) + } + + static var zero: EdgeInsets { + .init(top: 0, leading: 0, bottom: 0, trailing: 0) + } + + static func symmetric(_ value: CGFloat) -> EdgeInsets { + .init(top: value, leading: value, bottom: value, trailing: value) + } +} diff --git a/ConversationsClassic/View/UIToolkit/KeyboardDisposableModifier.swift b/old/View/UIToolkit/KeyboardDisposableModifier.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/KeyboardDisposableModifier.swift rename to old/View/UIToolkit/KeyboardDisposableModifier.swift diff --git a/old/View/UIToolkit/Typography.swift b/old/View/UIToolkit/Typography.swift new file mode 100644 index 0000000..db856f3 --- /dev/null +++ b/old/View/UIToolkit/Typography.swift @@ -0,0 +1,13 @@ +import Foundation +import SwiftUI + +extension Font { + static let head1l = Font.system(size: 34, weight: .light, design: .rounded) + static let head1r = Font.system(size: 34, weight: .regular, design: .rounded) + static let head2 = Font.system(size: 20, weight: .regular, design: .rounded) + static let body1 = Font.system(size: 18, weight: .regular, design: .rounded) + static let body2 = Font.system(size: 16, weight: .regular, design: .rounded) + static let body3 = Font.system(size: 14, weight: .regular, design: .rounded) + static let sub1 = Font.system(size: 10, weight: .regular, design: .rounded) + static let sub2 = Font.system(size: 8, weight: .regular, design: .rounded) +} diff --git a/ConversationsClassic/View/UIToolkit/UIImage+Crop.swift b/old/View/UIToolkit/UIImage+Crop.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/UIImage+Crop.swift rename to old/View/UIToolkit/UIImage+Crop.swift diff --git a/old/View/UIToolkit/Vibration.swift b/old/View/UIToolkit/Vibration.swift new file mode 100644 index 0000000..3eee66b --- /dev/null +++ b/old/View/UIToolkit/Vibration.swift @@ -0,0 +1,17 @@ +import SwiftUI +import UIKit + +enum Vibration: String { + case error + case success + + public func vibrate() { + switch self { + case .error: + UINotificationFeedbackGenerator().notificationOccurred(.error) + + case .success: + UINotificationFeedbackGenerator().notificationOccurred(.success) + } + } +} diff --git a/old/View/UIToolkit/View+Debug.swift b/old/View/UIToolkit/View+Debug.swift new file mode 100644 index 0000000..34f7c65 --- /dev/null +++ b/old/View/UIToolkit/View+Debug.swift @@ -0,0 +1,35 @@ +import SwiftUI + +#if DEBUG + private let rainbowDebugColors = [ + Color.purple, + Color.blue, + Color.green, + Color.yellow, + Color.orange, + Color.red, + Color.pink, + Color.black.opacity(0.5), + Color.teal, + Color.gray, + Color.mint, + Color.cyan + ] + + public extension Color { + static func random(randomOpacity: Bool = false) -> Color { + Color( + red: .random(in: 0 ... 1), + green: .random(in: 0 ... 1), + blue: .random(in: 0 ... 1), + opacity: randomOpacity ? .random(in: 0 ... 1) : 1 + ) + } + } + + extension View { + func rainbowDebug() -> some View { + background(Color.random()) + } + } +#endif diff --git a/old/View/UIToolkit/View+If.swift b/old/View/UIToolkit/View+If.swift new file mode 100644 index 0000000..f6611ca --- /dev/null +++ b/old/View/UIToolkit/View+If.swift @@ -0,0 +1,11 @@ +import SwiftUI + +public extension View { + @ViewBuilder func `if`(_ condition: @autoclosure () -> Bool, transform: (Self) -> Content) -> some View { + if condition() { + transform(self) + } else { + self + } + } +} diff --git a/ConversationsClassic/View/UIToolkit/View+Loader.swift b/old/View/UIToolkit/View+Loader.swift similarity index 100% rename from ConversationsClassic/View/UIToolkit/View+Loader.swift rename to old/View/UIToolkit/View+Loader.swift diff --git a/old/View/UIToolkit/View+OnLoad.swift b/old/View/UIToolkit/View+OnLoad.swift new file mode 100644 index 0000000..4206bff --- /dev/null +++ b/old/View/UIToolkit/View+OnLoad.swift @@ -0,0 +1,27 @@ +import SwiftUI + +// MARK: - On load +extension View { + func onLoad(_ action: @escaping () -> Void) -> some View { + modifier(ViewDidLoadModifier(action)) + } +} + +private struct ViewDidLoadModifier: ViewModifier { + private let action: () -> Void + + @State private var didLoad = false + + init(_ action: @escaping () -> Void) { + self.action = action + } + + func body(content: Content) -> some View { + content.onAppear { + if !didLoad { + didLoad.toggle() + action() + } + } + } +} diff --git a/old/View/UIToolkit/View+TappableArea.swift b/old/View/UIToolkit/View+TappableArea.swift new file mode 100644 index 0000000..8c659d4 --- /dev/null +++ b/old/View/UIToolkit/View+TappableArea.swift @@ -0,0 +1,27 @@ +import SwiftUI + +extension View { + func tappablePadding(_ insets: EdgeInsets, onTap: @escaping () -> Void) -> some View { + modifier(TappablePadding(insets: insets, onTap: onTap)) + } +} + +struct TappablePadding: ViewModifier { + let insets: EdgeInsets + let onTap: () -> Void + + public init(insets: EdgeInsets, onTap: @escaping () -> Void) { + self.insets = insets + self.onTap = onTap + } + + public func body(content: Content) -> some View { + content + .padding(insets) + .contentShape(Rectangle()) + .onTapGesture { + onTap() + } + .padding(insets.inverted) + } +} diff --git a/project.yml b/project.yml index ffa2075..4b35192 100644 --- a/project.yml +++ b/project.yml @@ -58,6 +58,7 @@ targets: - path: ConversationsClassic excludes: - .nvim + - old settings: TARGETED_DEVICE_FAMILY: 1 DEBUG_INFORMATION_FORMAT: dwarf-with-dsym