mirror of
https://github.com/bitwarden/ios.git
synced 2025-12-11 04:34:55 -06:00
Watch shared code (#313)
This commit is contained in:
parent
08b4357e77
commit
0e1ea6e9fb
@ -42,6 +42,7 @@ opt_in_rules:
|
||||
excluded:
|
||||
- BitwardenShared/UI/Platform/Application/Support/Generated
|
||||
- BitwardenWatchApp
|
||||
- BitwardenWatchShared
|
||||
- build
|
||||
- vendor/bundle
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ struct AvatarView: View {
|
||||
var textColor = Color.black
|
||||
var initials = ""
|
||||
|
||||
init(_ user: User?) {
|
||||
init(_ user: UserDTO?) {
|
||||
let source = user?.name ?? user?.email
|
||||
var upperCaseText: String? = nil
|
||||
|
||||
@ -80,6 +80,12 @@ struct AvatarView: View {
|
||||
|
||||
struct AvatarView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
AvatarView(User(id: "zxc", email: "asdfasdf@gmail.com", name: "John Snow"))
|
||||
AvatarView(
|
||||
UserDTO(
|
||||
email: "asdfasdf@gmail.com",
|
||||
id: "zxc",
|
||||
name: "John Snow"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,15 +17,21 @@ public extension CipherEntity {
|
||||
}
|
||||
|
||||
extension CipherEntity: Identifiable {
|
||||
func toCipher() -> Cipher {
|
||||
var loginUrisArray: [LoginUri]?
|
||||
func toCipher() -> CipherDTO {
|
||||
var loginUrisArray: [LoginUriDTO]?
|
||||
if loginUris != nil {
|
||||
loginUrisArray = try? JSONDecoder().decode([LoginUri].self, from: loginUris!.data(using: .utf8)!)
|
||||
loginUrisArray = try? JSONDecoder().decode([LoginUriDTO].self, from: loginUris!.data(using: .utf8)!)
|
||||
}
|
||||
|
||||
return Cipher(id: id,
|
||||
name: name,
|
||||
userId: userId,
|
||||
login: Login(username: username, totp: totp, uris: loginUrisArray))
|
||||
return CipherDTO(
|
||||
id: id,
|
||||
login: LoginDTO(
|
||||
totp: totp,
|
||||
uris: loginUrisArray,
|
||||
username: username
|
||||
),
|
||||
name: name,
|
||||
userId: userId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ class IconImageHelper {
|
||||
|
||||
private init() {}
|
||||
|
||||
func getLoginIconImage(_ cipher: Cipher) -> String? {
|
||||
func getLoginIconImage(_ cipher: CipherDTO) -> String? {
|
||||
guard let uris = cipher.login.uris, !uris.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,30 +1,6 @@
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
struct Cipher: Identifiable, Codable {
|
||||
enum CodingKeys: CodingKey {
|
||||
case id
|
||||
case name
|
||||
case login
|
||||
}
|
||||
|
||||
var id: String
|
||||
var name: String?
|
||||
var userId: String?
|
||||
var login: Login
|
||||
}
|
||||
|
||||
struct Login: Codable {
|
||||
var username: String?
|
||||
var totp: String?
|
||||
var uris: [LoginUri]?
|
||||
}
|
||||
|
||||
struct LoginUri: Codable {
|
||||
var uri: String?
|
||||
}
|
||||
|
||||
extension Cipher {
|
||||
extension CipherDTO {
|
||||
func toCipherEntity(moContext: NSManagedObjectContext) -> CipherEntity {
|
||||
let entity = CipherEntity(context: moContext)
|
||||
entity.id = id
|
||||
@ -1,59 +1,71 @@
|
||||
import Foundation
|
||||
|
||||
enum CipherMock {
|
||||
static let ciphers: [Cipher] = [
|
||||
Cipher(
|
||||
static let ciphers: [CipherDTO] = [
|
||||
CipherDTO(
|
||||
id: "0",
|
||||
name: "MySite",
|
||||
userId: "123123",
|
||||
login: Login(
|
||||
username: "test@testing.com",
|
||||
login: LoginDTO(
|
||||
totp: "otpauth://account?period=10&secret=LLLLLLLLLLLLLLLL",
|
||||
uris: cipherLoginUris
|
||||
)
|
||||
uris: cipherLoginUris,
|
||||
username: "test@testing.com"
|
||||
),
|
||||
name: "MySite",
|
||||
userId: "123123"
|
||||
),
|
||||
Cipher(
|
||||
CipherDTO(
|
||||
id: "1",
|
||||
login: LoginDTO(
|
||||
totp: "LLLLLLLLLLLLLLLL",
|
||||
uris: cipherLoginUris,
|
||||
username: "thisisatest@testing.com"
|
||||
),
|
||||
name: "GitHub",
|
||||
userId: "123123",
|
||||
login: Login(username: "thisisatest@testing.com", totp: "LLLLLLLLLLLLLLLL", uris: cipherLoginUris)
|
||||
userId: "123123"
|
||||
),
|
||||
Cipher(
|
||||
CipherDTO(
|
||||
id: "2",
|
||||
name: "No user",
|
||||
userId: "123123",
|
||||
login: Login(
|
||||
username: nil,
|
||||
login: LoginDTO(
|
||||
totp: "otpauth://account?period=10&digits=8&algorithm=sha256&secret=LLLLLLLLLLLLLLLL",
|
||||
uris: cipherLoginUris
|
||||
)
|
||||
uris: cipherLoginUris,
|
||||
username: nil
|
||||
),
|
||||
name: "No user",
|
||||
userId: "123123"
|
||||
),
|
||||
Cipher(
|
||||
CipherDTO(
|
||||
id: "3",
|
||||
name: "Site 2",
|
||||
userId: "123123",
|
||||
login: Login(
|
||||
username: "longtestemail000000@fastmailasdfasdf.com",
|
||||
login: LoginDTO(
|
||||
totp: "otpauth://account?period=10&digits=7&algorithm=sha512&secret=LLLLLLLLLLLLLLLL",
|
||||
uris: cipherLoginUris
|
||||
)
|
||||
uris: cipherLoginUris,
|
||||
username: "longtestemail000000@fastmailasdfasdf.com"
|
||||
),
|
||||
name: "Site 2",
|
||||
userId: "123123"
|
||||
),
|
||||
Cipher(
|
||||
CipherDTO(
|
||||
id: "4",
|
||||
login: LoginDTO(
|
||||
totp: "steam://LLLLLLLLLLLLLLLL",
|
||||
uris: cipherLoginUris,
|
||||
username: "user3"
|
||||
),
|
||||
name: "Really long name for a site that is used for a totp",
|
||||
userId: "123123",
|
||||
login: Login(username: "user3", totp: "steam://LLLLLLLLLLLLLLLL", uris: cipherLoginUris)
|
||||
userId: "123123"
|
||||
),
|
||||
Cipher(
|
||||
CipherDTO(
|
||||
id: "5",
|
||||
login: LoginDTO(
|
||||
totp: "steam://LLLLLLLLLLLLLLLL",
|
||||
uris: cipherLoginUris,
|
||||
username: "u"
|
||||
),
|
||||
name: "Short",
|
||||
userId: "123123",
|
||||
login: Login(username: "u", totp: "steam://LLLLLLLLLLLLLLLL", uris: cipherLoginUris)
|
||||
userId: "123123"
|
||||
),
|
||||
]
|
||||
|
||||
static let cipherLoginUris: [LoginUri] = [
|
||||
LoginUri(uri: "github.com"),
|
||||
LoginUri(uri: "example2.com"),
|
||||
static let cipherLoginUris: [LoginUriDTO] = [
|
||||
LoginUriDTO(uri: "github.com"),
|
||||
LoginUriDTO(uri: "example2.com"),
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
struct User: Codable {
|
||||
var id: String
|
||||
var email: String?
|
||||
var name: String?
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
struct WatchDTO: Codable {
|
||||
var state: BWState
|
||||
var ciphers: [Cipher]?
|
||||
var userData: User?
|
||||
var environmentData: EnvironmentUrlDataDto?
|
||||
// var settingsData: SettingsDataDto?
|
||||
|
||||
init(state: BWState) {
|
||||
self.state = state
|
||||
ciphers = nil
|
||||
userData = nil
|
||||
environmentData = nil
|
||||
}
|
||||
}
|
||||
|
||||
struct EnvironmentUrlDataDto: Codable {
|
||||
var base: String?
|
||||
var icons: String?
|
||||
}
|
||||
|
||||
// struct SettingsDataDto : Codable {
|
||||
// var vaultTimeoutInMinutes: Int?
|
||||
// var vaultTimeoutAction: VaultTimeoutAction
|
||||
// }
|
||||
@ -2,9 +2,9 @@ import CoreData
|
||||
import Foundation
|
||||
|
||||
protocol CipherServiceProtocol {
|
||||
func getCipher(_ id: String) -> Cipher?
|
||||
func fetchCiphers(_ withUserId: String?) -> [Cipher]
|
||||
func saveCiphers(_ ciphers: [Cipher], completionHandler: @escaping () -> Void)
|
||||
func getCipher(_ id: String) -> CipherDTO?
|
||||
func fetchCiphers(_ withUserId: String?) -> [CipherDTO]
|
||||
func saveCiphers(_ ciphers: [CipherDTO], completionHandler: @escaping () -> Void)
|
||||
func deleteAll(_ withUserId: String?, completionHandler: @escaping () -> Void)
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ class CipherService {
|
||||
|
||||
private init() {}
|
||||
|
||||
func getCipher(_ id: String) -> Cipher? {
|
||||
func getCipher(_ id: String) -> CipherDTO? {
|
||||
let predicate = NSPredicate(
|
||||
format: "id = %@",
|
||||
id as CVarArg
|
||||
@ -33,7 +33,7 @@ class CipherService {
|
||||
// MARK: - CipherServiceProtocol
|
||||
|
||||
extension CipherService: CipherServiceProtocol {
|
||||
func fetchCiphers(_ withUserId: String?) -> [Cipher] {
|
||||
func fetchCiphers(_ withUserId: String?) -> [CipherDTO] {
|
||||
let result: Result<[CipherEntity], Error> = dbHelper.fetch(
|
||||
CipherEntity.self,
|
||||
"CipherEntity",
|
||||
@ -47,11 +47,11 @@ extension CipherService: CipherServiceProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func saveCiphers(_ ciphers: [Cipher], completionHandler: @escaping () -> Void) {
|
||||
func saveCiphers(_ ciphers: [CipherDTO], completionHandler: @escaping () -> Void) {
|
||||
let cipherIds = ciphers.map(\.id)
|
||||
deleteAll(ciphers[0].userId, notIn: cipherIds) {
|
||||
self.dbHelper.insertBatch("CipherEntity", items: ciphers) { item, context in
|
||||
guard let cipher = item as! Cipher? else { return [:] }
|
||||
guard let cipher = item as! CipherDTO? else { return [:] }
|
||||
let c = cipher.toCipherEntity(moContext: context)
|
||||
guard let data = try? JSONEncoder().encode(c) else {
|
||||
Log.e("Error converting to data")
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
class CipherServiceMock: CipherServiceProtocol {
|
||||
func fetchCiphers(_: String?) -> [Cipher] {
|
||||
func fetchCiphers(_: String?) -> [CipherDTO] {
|
||||
ciphers
|
||||
}
|
||||
|
||||
@ -9,15 +9,15 @@ class CipherServiceMock: CipherServiceProtocol {
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
func getCipher(_ id: String) -> Cipher? {
|
||||
func getCipher(_ id: String) -> CipherDTO? {
|
||||
CipherMock.ciphers.first { ci in
|
||||
ci.id == id
|
||||
}
|
||||
}
|
||||
|
||||
func saveCiphers(_: [Cipher], completionHandler _: @escaping () -> Void) {}
|
||||
func saveCiphers(_: [CipherDTO], completionHandler _: @escaping () -> Void) {}
|
||||
|
||||
private var ciphers = [Cipher]()
|
||||
private var ciphers = [CipherDTO]()
|
||||
|
||||
init() {
|
||||
ciphers = CipherMock.ciphers
|
||||
|
||||
@ -31,11 +31,11 @@ class StateService {
|
||||
}
|
||||
}
|
||||
|
||||
func getUser() -> User? {
|
||||
KeychainHelper.standard.read(CURRENT_USER_KEY, User.self)
|
||||
func getUser() -> UserDTO? {
|
||||
KeychainHelper.standard.read(CURRENT_USER_KEY, UserDTO.self)
|
||||
}
|
||||
|
||||
func setUser(user: User?) {
|
||||
func setUser(user: UserDTO?) {
|
||||
guard let user else {
|
||||
KeychainHelper.standard.delete(CURRENT_USER_KEY)
|
||||
return
|
||||
|
||||
@ -2,7 +2,7 @@ import Foundation
|
||||
import SwiftUI
|
||||
|
||||
class CipherDetailsViewModel: ObservableObject {
|
||||
@Published var cipher: Cipher
|
||||
@Published var cipher: CipherDTO
|
||||
|
||||
@Published var totpFormatted: String = ""
|
||||
@Published var progress: Double = 1
|
||||
@ -13,7 +13,7 @@ class CipherDetailsViewModel: ObservableObject {
|
||||
var period: Int
|
||||
var timer: Timer? = nil
|
||||
|
||||
init(cipher: Cipher) {
|
||||
init(cipher: CipherDTO) {
|
||||
self.cipher = cipher
|
||||
key = cipher.login.totp!
|
||||
period = TotpService.shared.getPeriodFrom(key)
|
||||
|
||||
@ -6,12 +6,12 @@ class CipherListViewModel: ObservableObject {
|
||||
var cipherService: CipherServiceProtocol
|
||||
var watchConnectivityManager = WatchConnectivityManager.shared
|
||||
|
||||
@Published private var ciphers: [Cipher] = []
|
||||
@Published var filteredCiphers: [Cipher] = []
|
||||
@Published private var ciphers: [CipherDTO] = []
|
||||
@Published var filteredCiphers: [CipherDTO] = []
|
||||
@Published var updateHack: Bool = false
|
||||
@Published var showingSheet = false
|
||||
@Published var currentState = BWState.valid
|
||||
@Published var user: User?
|
||||
@Published var user: UserDTO?
|
||||
|
||||
@Published var searchTerm: String = ""
|
||||
|
||||
@ -36,12 +36,19 @@ class CipherListViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
// WORKAROUND: To display 0 search results
|
||||
if !searchTerm.isEmpty, returnCiphers.isEmpty {
|
||||
returnCiphers.append(Cipher(
|
||||
id: "-1",
|
||||
name: "NoItemsFound",
|
||||
login: Login(username: "", totp: "", uris: nil)
|
||||
))
|
||||
if !searchTerm.isEmpty,
|
||||
returnCiphers.isEmpty {
|
||||
returnCiphers.append(
|
||||
CipherDTO(
|
||||
id: "-1",
|
||||
login: LoginDTO(
|
||||
totp: "",
|
||||
uris: nil,
|
||||
username: ""
|
||||
),
|
||||
name: "NoItemsFound"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if searchTerm.isEmpty {
|
||||
@ -84,7 +91,7 @@ class CipherListViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func cipherContains(_ cipher: Cipher, _: String) -> Bool {
|
||||
func cipherContains(_ cipher: CipherDTO, _: String) -> Bool {
|
||||
if searchTerm.isEmpty {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ struct CipherDetailsView: View {
|
||||
|
||||
let iconSize: CGSize = .init(width: 30, height: 30)
|
||||
|
||||
init(cipher: Cipher) {
|
||||
init(cipher: CipherDTO) {
|
||||
cipherDetailsViewModel = CipherDetailsViewModel(cipher: cipher)
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import SwiftUI
|
||||
|
||||
struct CipherItemView: View {
|
||||
let cipher: Cipher
|
||||
let cipher: CipherDTO
|
||||
let maxWidth: CGFloat
|
||||
|
||||
init(_ cipher: Cipher, _ maxWidth: CGFloat) {
|
||||
init(_ cipher: CipherDTO, _ maxWidth: CGFloat) {
|
||||
self.cipher = cipher
|
||||
self.maxWidth = maxWidth
|
||||
}
|
||||
|
||||
@ -129,7 +129,11 @@ struct ContentView_Previews: PreviewProvider {
|
||||
var v = CipherListView()
|
||||
StateService.shared.currentState = .valid
|
||||
v.viewModel = CipherListViewModel(CipherServiceMock())
|
||||
v.viewModel.user = User(id: "zxc", email: "testing@test.com", name: "Tester")
|
||||
v.viewModel.user = UserDTO(
|
||||
email: "testing@test.com",
|
||||
id: "zxc",
|
||||
name: "Tester"
|
||||
)
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,34 +84,9 @@ extension WatchConnectivityManager: WCSessionDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
let decoder = MessagePackDecoder()
|
||||
decoder.userInfo[MessagePackDecoder.dataSpecKey] = DataSpecBuilder()
|
||||
.append("state")
|
||||
.appendArray("ciphers", DataSpecBuilder()
|
||||
.append("id")
|
||||
.append("name")
|
||||
.appendObj("login", DataSpecBuilder()
|
||||
.append("username")
|
||||
.append("totp")
|
||||
.appendArray("uris", DataSpecBuilder()
|
||||
.append("uri")
|
||||
.build())
|
||||
.build())
|
||||
.build())
|
||||
.appendObj("userData", DataSpecBuilder()
|
||||
.append("id")
|
||||
.append("email")
|
||||
.append("name")
|
||||
.build())
|
||||
.appendObj("environmentData", DataSpecBuilder()
|
||||
.append("base")
|
||||
.append("icons")
|
||||
.build())
|
||||
.build()
|
||||
|
||||
let rawData = try nsRawData.decompressed(using: .lzfse)
|
||||
|
||||
let watchDTO = try decoder.decode(WatchDTO.self, from: Data(referencing: rawData))
|
||||
let watchDTO = try MessagePackDecoder().decode(WatchDTO.self, from: Data(referencing: rawData))
|
||||
|
||||
let previousUserId = StateService.shared.getUser()?.id
|
||||
|
||||
|
||||
@ -21,8 +21,4 @@ struct AnyCodingKey: CodingKey, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
extension AnyCodingKey: Hashable {
|
||||
var hashValue: Int {
|
||||
intValue?.hashValue ?? stringValue.hashValue
|
||||
}
|
||||
}
|
||||
extension AnyCodingKey: Hashable {}
|
||||
@ -6,7 +6,7 @@ public struct DataSpec {
|
||||
let isArray: Bool
|
||||
let dataSpecBuilder: DataSpecBuilder?
|
||||
|
||||
init(_ name: String, _ isObj: Bool, _ isArray: Bool, _ dataSpecBuilder: DataSpecBuilder?) {
|
||||
public init(_ name: String, _ isObj: Bool, _ isArray: Bool, _ dataSpecBuilder: DataSpecBuilder?) {
|
||||
self.name = name
|
||||
self.isObj = isObj
|
||||
self.isArray = isArray
|
||||
@ -18,37 +18,37 @@ public class DataSpecBuilder: NSCopying {
|
||||
var specs: [DataSpec] = []
|
||||
var specsIterator: IndexingIterator<[DataSpec]>
|
||||
|
||||
init() {
|
||||
public init() {
|
||||
specsIterator = IndexingIterator(_elements: [])
|
||||
}
|
||||
|
||||
func append(_ name: String) -> DataSpecBuilder {
|
||||
public func append(_ name: String) -> DataSpecBuilder {
|
||||
append(DataSpec(name, false, false, nil))
|
||||
}
|
||||
|
||||
func appendObj(_ name: String, _ dataSpecBuilder: DataSpecBuilder) -> DataSpecBuilder {
|
||||
public func appendObj(_ name: String, _ dataSpecBuilder: DataSpecBuilder) -> DataSpecBuilder {
|
||||
append(DataSpec(name, true, false, dataSpecBuilder))
|
||||
}
|
||||
|
||||
func appendArray(_ name: String) -> DataSpecBuilder {
|
||||
public func appendArray(_ name: String) -> DataSpecBuilder {
|
||||
append(DataSpec(name, false, true, nil))
|
||||
}
|
||||
|
||||
func appendArray(_ name: String, _ dataSpecBuilder: DataSpecBuilder) -> DataSpecBuilder {
|
||||
public func appendArray(_ name: String, _ dataSpecBuilder: DataSpecBuilder) -> DataSpecBuilder {
|
||||
append(DataSpec(name, false, true, dataSpecBuilder))
|
||||
}
|
||||
|
||||
func append(_ spec: DataSpec) -> DataSpecBuilder {
|
||||
public func append(_ spec: DataSpec) -> DataSpecBuilder {
|
||||
specs.append(spec)
|
||||
return self
|
||||
}
|
||||
|
||||
func build() -> DataSpecBuilder {
|
||||
public func build() -> DataSpecBuilder {
|
||||
specsIterator = specs.makeIterator()
|
||||
return self
|
||||
}
|
||||
|
||||
func next() -> DataSpec {
|
||||
public func next() -> DataSpec {
|
||||
specsIterator.next()!
|
||||
}
|
||||
|
||||
@ -47,15 +47,15 @@ public final class MessagePackDecoder {
|
||||
case cast
|
||||
}
|
||||
|
||||
static var nonMatchingFloatDecodingStrategyKey: CodingUserInfoKey {
|
||||
public static var nonMatchingFloatDecodingStrategyKey: CodingUserInfoKey {
|
||||
CodingUserInfoKey(rawValue: "nonMatchingFloatDecodingStrategyKey")!
|
||||
}
|
||||
|
||||
static var dataSpecKey: CodingUserInfoKey {
|
||||
public static var dataSpecKey: CodingUserInfoKey {
|
||||
CodingUserInfoKey(rawValue: "dataSpecKey")!
|
||||
}
|
||||
|
||||
static var isArrayDataSpecKey: CodingUserInfoKey {
|
||||
public static var isArrayDataSpecKey: CodingUserInfoKey {
|
||||
CodingUserInfoKey(rawValue: "isArrayDataSpecKey")!
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,20 @@
|
||||
import Foundation
|
||||
|
||||
enum BWState: Int, Codable {
|
||||
// MARK: - BWState
|
||||
|
||||
/// The state of the watch app.
|
||||
///
|
||||
public enum BWState: Int, Codable {
|
||||
case valid = 0
|
||||
case needLogin = 1
|
||||
case needPremium = 2
|
||||
case needSetup = 3
|
||||
case need2FAItem = 4
|
||||
case syncing = 5
|
||||
/// case needUnlock = 6
|
||||
case needDeviceOwnerAuth = 7
|
||||
case debug = 255
|
||||
|
||||
var isDestructive: Bool {
|
||||
public var isDestructive: Bool {
|
||||
self == .needSetup || self == .needLogin || self == .needPremium || self == .need2FAItem
|
||||
}
|
||||
}
|
||||
106
BitwardenWatchShared/Models/CipherDTO.swift
Normal file
106
BitwardenWatchShared/Models/CipherDTO.swift
Normal file
@ -0,0 +1,106 @@
|
||||
import Foundation
|
||||
|
||||
// MARK: - CipherDTO
|
||||
|
||||
/// The simplified cipher model used to communicate between the watch and the main app.
|
||||
///
|
||||
public struct CipherDTO: Identifiable, Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The id of the cipher.
|
||||
public var id: String
|
||||
|
||||
/// The login model of the cipher (all ciphers in the watch are of type login).
|
||||
public var login: LoginDTO
|
||||
|
||||
/// The name of the cipher.
|
||||
public var name: String?
|
||||
|
||||
/// The user id associated with the cipher.
|
||||
public var userId: String?
|
||||
|
||||
enum CodingKeys: CodingKey {
|
||||
case id
|
||||
case name
|
||||
case login
|
||||
}
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Initializes a `CipherDTO`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - id: The id of the cipher.
|
||||
/// - login: The login model of the cipher (all ciphers in the watch are of type login).
|
||||
/// - name: The name of the cipher.
|
||||
/// - userId: The user id associated with the cipher.
|
||||
///
|
||||
public init(
|
||||
id: String,
|
||||
login: LoginDTO,
|
||||
name: String? = nil,
|
||||
userId: String? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.login = login
|
||||
self.name = name
|
||||
self.userId = userId
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - LoginDTO
|
||||
|
||||
/// The simplified login model used to communicate between the watch and the main app.
|
||||
///
|
||||
public struct LoginDTO: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The totp code for the login.
|
||||
public var totp: String?
|
||||
|
||||
/// The list of uri's for the login.
|
||||
public var uris: [LoginUriDTO]?
|
||||
|
||||
/// The login associated with the username.
|
||||
public var username: String?
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Initializes a `LoginDTO`,
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - totp: The totp code for the login.
|
||||
/// - uris: The list of uri's for the login.
|
||||
/// - username: The login associated with the username.
|
||||
///
|
||||
public init(
|
||||
totp: String? = nil,
|
||||
uris: [LoginUriDTO]? = nil,
|
||||
username: String? = nil
|
||||
) {
|
||||
self.totp = totp
|
||||
self.uris = uris
|
||||
self.username = username
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - LoginUriDTO
|
||||
|
||||
/// The simplified login uri used to communicate between the watch and the main app.
|
||||
///
|
||||
public struct LoginUriDTO: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The uri of the login.
|
||||
public var uri: String?
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Initializes a `LoginUriDTO`,
|
||||
///
|
||||
/// - Parameter uri: The uri of the login.
|
||||
///
|
||||
public init(uri: String? = nil) {
|
||||
self.uri = uri
|
||||
}
|
||||
}
|
||||
28
BitwardenWatchShared/Models/EnvironmentUrlDTO.swift
Normal file
28
BitwardenWatchShared/Models/EnvironmentUrlDTO.swift
Normal file
@ -0,0 +1,28 @@
|
||||
import Foundation
|
||||
|
||||
// MARK: - EnvironmentUrlDTO
|
||||
|
||||
/// The environment data used to communicate between the watch and the main app.
|
||||
///
|
||||
public struct EnvironmentUrlDTO: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The base url.
|
||||
public var base: String?
|
||||
|
||||
/// The url used for loading icons.
|
||||
public var icons: String?
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Initializes a `EnvironmentUrlDTO`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - base: The base url.
|
||||
/// - icons: The url used for loading icons.
|
||||
///
|
||||
public init(base: String? = nil, icons: String? = nil) {
|
||||
self.base = base
|
||||
self.icons = icons
|
||||
}
|
||||
}
|
||||
32
BitwardenWatchShared/Models/UserDTO.swift
Normal file
32
BitwardenWatchShared/Models/UserDTO.swift
Normal file
@ -0,0 +1,32 @@
|
||||
import Foundation
|
||||
|
||||
// MARK: - UserDTO
|
||||
|
||||
/// The simplified user model used to communicate between the watch and the main app.
|
||||
public struct UserDTO: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The user's email.
|
||||
public var email: String?
|
||||
|
||||
/// The user's id.
|
||||
public var id: String
|
||||
|
||||
/// The user's name.
|
||||
public var name: String?
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Initializes a `UserDTO`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - email: The user's email.
|
||||
/// - id: The user's id.
|
||||
/// - name: The user's name.
|
||||
///
|
||||
public init(email: String? = nil, id: String, name: String? = nil) {
|
||||
self.email = email
|
||||
self.id = id
|
||||
self.name = name
|
||||
}
|
||||
}
|
||||
43
BitwardenWatchShared/Models/WatchDTO.swift
Normal file
43
BitwardenWatchShared/Models/WatchDTO.swift
Normal file
@ -0,0 +1,43 @@
|
||||
import Foundation
|
||||
|
||||
// MARK: - WatchDTO
|
||||
|
||||
/// The structure of the data used to communicate between the watch and the main app.
|
||||
///
|
||||
public struct WatchDTO: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The state of the watch app.
|
||||
public var state: BWState
|
||||
|
||||
/// The list of ciphers to display.
|
||||
public var ciphers: [CipherDTO]?
|
||||
|
||||
/// The user data.
|
||||
public var userData: UserDTO?
|
||||
|
||||
/// The urls to use.
|
||||
public var environmentData: EnvironmentUrlDTO?
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Initializes a `WatchDTO`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - state: The state of the watch app.
|
||||
/// - ciphers: The list of ciphers to display.
|
||||
/// - userData: The user data.
|
||||
/// - environmentData: The urls to use.
|
||||
///
|
||||
public init(
|
||||
state: BWState,
|
||||
ciphers: [CipherDTO]? = nil,
|
||||
userData: UserDTO? = nil,
|
||||
environmentData: EnvironmentUrlDTO? = nil
|
||||
) {
|
||||
self.state = state
|
||||
self.ciphers = ciphers
|
||||
self.userData = userData
|
||||
self.environmentData = environmentData
|
||||
}
|
||||
}
|
||||
@ -323,6 +323,7 @@ targets:
|
||||
optional: true
|
||||
- path: BitwardenShared/UI/Platform/Application/Support/Generated/Localizations.swift
|
||||
optional: true
|
||||
- path: BitwardenWatchShared
|
||||
dependencies:
|
||||
- package: BitwardenSdk
|
||||
- package: Networking
|
||||
@ -370,8 +371,9 @@ targets:
|
||||
INFOPLIST_FILE: BitwardenWatchApp/Info.plist
|
||||
sources:
|
||||
- path: BitwardenWatchApp
|
||||
- path: BitwardenWatchShared
|
||||
- path: BitwardenWatchApp/GoogleService-Info.plist
|
||||
buildPhase: resources
|
||||
dependencies:
|
||||
- package: Firebase
|
||||
product: FirebaseCrashlytics
|
||||
product: FirebaseCrashlytics
|
||||
Loading…
x
Reference in New Issue
Block a user