Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: WatchOS app #5476

Merged
merged 98 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
96901bb
Add WatchOS App Target
djorkaeffalexandre Jan 11, 2024
31c1181
Add WatchConnectivity
djorkaeffalexandre Jan 15, 2024
077686d
Add ServerListView & RoomListView
djorkaeffalexandre Jan 17, 2024
7ced062
Add MessageListView & MessageView
djorkaeffalexandre Jan 17, 2024
9668aed
Remove unnecessary ViewModel layer
djorkaeffalexandre Jan 18, 2024
2fdf0e2
Add AttachmentView
djorkaeffalexandre Jan 18, 2024
8f3bb1a
re-indent
djorkaeffalexandre Jan 18, 2024
0672f56
Add Client Certificate
djorkaeffalexandre Jan 19, 2024
64bd23e
Remove Customized Notification
djorkaeffalexandre Jan 19, 2024
cf1cbb7
Create Dependency Injection module
djorkaeffalexandre Jan 19, 2024
91968be
Use Dependency propertyWrapper
djorkaeffalexandre Jan 19, 2024
16b2a12
Refactor ServerListView
djorkaeffalexandre Jan 20, 2024
7b68522
Lazy Inject logged in dependencies
djorkaeffalexandre Jan 20, 2024
48de9ea
Remove stateProvider
djorkaeffalexandre Jan 20, 2024
9d42552
Reverse ScrollView
djorkaeffalexandre Jan 22, 2024
adb32a3
Deployment Target WatchOS 8
djorkaeffalexandre Jan 22, 2024
e638759
Prevent read on unlogged server
djorkaeffalexandre Jan 22, 2024
7281d84
Fix WatchOS 8 compatibility
djorkaeffalexandre Jan 23, 2024
02a1692
Improve ViewModel
djorkaeffalexandre Jan 23, 2024
045f208
Retry delaying servers loading
djorkaeffalexandre Jan 23, 2024
cf14b1c
Fix fastlane issues
diegolmello Jan 31, 2024
dc7848e
Explicit self
djorkaeffalexandre Jan 31, 2024
6c68321
Add watch provisioning to ci
diegolmello Jan 31, 2024
1f3d46e
Update CI Xcode to 15.2.0
diegolmello Jan 31, 2024
37c1649
Remove WatchOS 10 compat
djorkaeffalexandre Jan 31, 2024
567d88f
Update provisioning
djorkaeffalexandre Jan 31, 2024
2e8e115
ScenePhase observing
djorkaeffalexandre Feb 1, 2024
e97f6bd
Merge branch 'develop' into feat.watch
djorkaeffalexandre Feb 6, 2024
142d7a3
Merge branch 'develop' into feat.watch
djorkaeffalexandre Feb 15, 2024
1d964ce
Update ChatScrollView on WatchOS 10
djorkaeffalexandre Feb 15, 2024
5e70b0b
Remove unnecessary ScrollViewReader
djorkaeffalexandre Feb 15, 2024
0113dbe
Show initial loading
djorkaeffalexandre Feb 15, 2024
cdbab6e
Add ErrorActionHandler
djorkaeffalexandre Feb 15, 2024
fd8c099
Retry after an error
djorkaeffalexandre Feb 15, 2024
5b533fc
Client Certificate
djorkaeffalexandre Feb 21, 2024
7f151ef
Improve DependencyInjection
djorkaeffalexandre Feb 21, 2024
591da32
Add RocketChatRN Watch
djorkaeffalexandre Feb 21, 2024
bf812c0
Message Edited icon
djorkaeffalexandre Feb 23, 2024
e54aa21
Merge branch 'develop' into feat.watch
djorkaeffalexandre Feb 23, 2024
b0b1bf9
Change Product name
djorkaeffalexandre Feb 23, 2024
0398c8c
Change BuildableName
djorkaeffalexandre Mar 1, 2024
783a984
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Mar 1, 2024
b59d0d2
Localize messages
djorkaeffalexandre Mar 1, 2024
3b30a8d
Fix Image on Client-Certificate server
djorkaeffalexandre Mar 4, 2024
72dfeb4
Sort server list
djorkaeffalexandre Mar 4, 2024
539ccf8
Fix infinite rooms loading
djorkaeffalexandre Mar 4, 2024
885de66
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Mar 4, 2024
f36fca9
Build iOS Official
diegolmello Mar 7, 2024
d39e958
Rename to Workspaces
djorkaeffalexandre Mar 8, 2024
339f915
Merge branch 'feat.watch' of https://github.com/RocketChat/Rocket.Cha…
djorkaeffalexandre Mar 8, 2024
62edbff
Move Upload source maps to Bugsnag to last build phase
djorkaeffalexandre Mar 8, 2024
d29cfe4
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Mar 10, 2024
ea0910f
Add inputPaths
djorkaeffalexandre Mar 10, 2024
021f758
Set WKCompanionAppBundleIdentifier
djorkaeffalexandre Mar 10, 2024
ef77a73
Set ENABLE_USER_SCRIPT_SANDBOXING=NO
djorkaeffalexandre Mar 11, 2024
c255997
Check file script
djorkaeffalexandre Mar 12, 2024
29ea629
Merge branch 'develop' into feat.watch
diegolmello Mar 12, 2024
b457f7a
Change inputPath
djorkaeffalexandre Mar 12, 2024
c583b70
destroyPersistentStore
djorkaeffalexandre Mar 12, 2024
e887cf9
Support to system messages
djorkaeffalexandre Mar 12, 2024
48f3b78
Use sentence case
djorkaeffalexandre Mar 13, 2024
2cbcebe
Update colors
djorkaeffalexandre Mar 21, 2024
99c0351
New toolbar for WatchOS 10
djorkaeffalexandre Mar 21, 2024
797076b
New navigation flow
djorkaeffalexandre Mar 23, 2024
2de0acc
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Mar 23, 2024
94b9ff9
Add Deeplinking
djorkaeffalexandre Mar 23, 2024
d781bfd
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 2, 2024
3417000
Adjust spaces
djorkaeffalexandre Apr 2, 2024
4e0aeb8
Disable interaction on first sync for room
djorkaeffalexandre Apr 2, 2024
fc46f48
Hidden rooms
djorkaeffalexandre Apr 3, 2024
52a4ec4
Adjust real name use
djorkaeffalexandre Apr 6, 2024
2ec47ed
Add RoomInfoView
djorkaeffalexandre Apr 8, 2024
904bca3
Fix name being empty
djorkaeffalexandre Apr 12, 2024
f6fa904
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 12, 2024
d073a15
Add hideUnreadStatus
djorkaeffalexandre Apr 15, 2024
0265465
Prevent searching for 0 rooms
djorkaeffalexandre Apr 17, 2024
981f787
Set room as read on open
djorkaeffalexandre Apr 17, 2024
aa93f5b
Fetch the existing user
djorkaeffalexandre Apr 17, 2024
ae50e2f
Perform rooms & subs operations in a background context
djorkaeffalexandre Apr 18, 2024
07f9bf0
Update timestamp only once for server version < 4
djorkaeffalexandre Apr 18, 2024
3cf4a0b
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 18, 2024
88c5ad3
Address review comments
djorkaeffalexandre Apr 23, 2024
cdfa407
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 23, 2024
a83c997
Update localization
djorkaeffalexandre Apr 23, 2024
e59b868
Change executable name for Watch App
djorkaeffalexandre Apr 24, 2024
71e4e6e
Add missing watermelon db include
djorkaeffalexandre Apr 24, 2024
4720091
Update detox build command
djorkaeffalexandre Apr 24, 2024
d681a0e
No messages view
djorkaeffalexandre Apr 24, 2024
903fa99
Wait database processing to hide loading view
djorkaeffalexandre Apr 25, 2024
206cf4a
Update loaded state
djorkaeffalexandre Apr 25, 2024
e507669
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 25, 2024
f179c55
Observe Context changes
djorkaeffalexandre Apr 25, 2024
7bc911e
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 25, 2024
f1ca7f6
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 25, 2024
3a24726
Query by rid of notification payload
djorkaeffalexandre Apr 25, 2024
7eb2e86
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 25, 2024
079fd23
Fix push reply
djorkaeffalexandre Apr 26, 2024
8fc81fc
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Apr 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .detoxrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ module.exports = {
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/Rocket.Chat Experimental.app',
build:
'xcodebuild -workspace ios/RocketChatRN.xcworkspace -scheme RocketChatRN -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build'
'xcodebuild -workspace ios/RocketChatRN.xcworkspace -scheme RocketChatRN -configuration Debug -destination \'generic/platform=iphonesimulator\' -derivedDataPath ios/build'
},
'ios.release': {
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/Rocket.Chat Experimental.app',
build:
'xcodebuild -workspace ios/RocketChatRN.xcworkspace -scheme RocketChatRN -configuration Release -sdk iphonesimulator -derivedDataPath ios/build'
'xcodebuild -workspace ios/RocketChatRN.xcworkspace -scheme RocketChatRN -configuration Release -destination \'generic/platform=iphonesimulator\' -derivedDataPath ios/build'
},
'android.debug': {
type: 'android.apk',
Expand Down
1 change: 1 addition & 0 deletions app/lib/methods/helpers/sslPinning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const RCSSLPinning = Platform.select({
certificate = persistCertificate(name, certificate.password);
}
UserPreferences.setMap(extractHostname(server), certificate);
SSLPinning?.setCertificate(server, certificate.path, certificate.password);
djorkaeffalexandre marked this conversation as resolved.
Show resolved Hide resolved
}
}
},
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions ios/Experimental.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
},
{
"filename" : "1024 1.png",
"idiom" : "universal",
"platform" : "watchos",
"size" : "1024x1024"
}
],
"info" : {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions ios/Official.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
},
{
"filename" : "1024 1.png",
"idiom" : "universal",
"platform" : "watchos",
"size" : "1024x1024"
}
],
"info" : {
Expand Down
39 changes: 39 additions & 0 deletions ios/RocketChat Watch App/ActionHandler/ErrorActionHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Foundation

protocol ErrorActionHandling {
func handle(error: RocketChatError)
}

final class ErrorActionHandler {
@Dependency private var database: Database
@Dependency private var serversDB: ServersDatabase
@Dependency private var router: AppRouting

private let server: Server

init(server: Server) {
self.server = server
}

private func handleOnMain(error: RocketChatError) {
switch error {
case .server(let response):
router.present(error: response)
case .unauthorized:
router.route(to: [.loading, .serverList]) {
self.database.remove()
self.serversDB.remove(self.server)
}
case .unknown:
print("Unexpected error on Client.")
}
}
}

extension ErrorActionHandler: ErrorActionHandling {
func handle(error: RocketChatError) {
DispatchQueue.main.async {
self.handleOnMain(error: error)
}
}
}
83 changes: 83 additions & 0 deletions ios/RocketChat Watch App/AppRouter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import Foundation

protocol AppRouting {
func route(to route: Route)
func present(error: ErrorResponse)
func route(to routes: [Route], completion: (() -> Void)?)
}

final class AppRouter: ObservableObject {
@Published var error: ErrorResponse?

@Published var server: Server? {
didSet {
if server != oldValue, let server {
registerDependencies(in: server)
}
}
}

@Published var room: Room?

@Storage(.currentServer) private var currentURL: URL?

private func registerDependencies(in server: Server) {
Store.register(Database.self, factory: server.database)
Store.register(RocketChatClientProtocol.self, factory: RocketChatClient(server: server))
Store.register(MessageSending.self, factory: MessageSender(server: server))
Store.register(ErrorActionHandling.self, factory: ErrorActionHandler(server: server))
Store.register(MessagesLoading.self, factory: MessagesLoader())
Store.register(RoomsLoader.self, factory: RoomsLoader(server: server))
}
}

extension AppRouter: AppRouting {
func route(to route: Route) {
switch route {
case .roomList(let selectedServer):
currentURL = selectedServer.url
room = nil
server = selectedServer
case .room(let selectedServer, let selectedRoom):
currentURL = selectedServer.url
server = selectedServer
room = selectedRoom
case .serverList:
currentURL = nil
room = nil
server = nil
case .loading:
room = nil
server = nil
}
}

func present(error: ErrorResponse) {
guard self.error == nil else {
return
}

self.error = error
}
}

extension AppRouter {
func route(to routes: [Route], completion: (() -> Void)? = nil) {
guard let routeTo = routes.first else {
completion?()
return
}

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.route(to: routeTo)
self.route(to: Array(routes[1..<routes.count]), completion: completion)
}
}
}

enum Route: Equatable {
case loading
case serverList
case roomList(Server)
case room(Server, Room)
}
39 changes: 39 additions & 0 deletions ios/RocketChat Watch App/AppView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import SwiftUI

struct AppView: View {
@Storage(.currentServer) private var currentURL: URL?

@Dependency private var database: ServersDatabase

@StateObject private var router: AppRouter

init(router: AppRouter) {
_router = StateObject(wrappedValue: router)
}

var body: some View {
NavigationView {
ServerListView()
.environmentObject(router)
.environment(\.managedObjectContext, database.viewContext)
}
.onAppear {
loadRoute()
}
.sheet(item: $router.error) { error in
Text(error.error)
.multilineTextAlignment(.center)
.padding()
}
}

private func loadRoute() {
if let currentURL, let server = database.server(url: currentURL) {
router.route(to: .roomList(server))
} else if database.servers().count == 1, let server = database.servers().first {
router.route(to: .roomList(server))
} else {
router.route(to: .serverList)
}
}
}
6 changes: 6 additions & 0 deletions ios/RocketChat Watch App/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "channel-private.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "channel-public.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "discussions.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "message.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "teams-private.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "teams.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions ios/RocketChat Watch App/Client/Adapters/JSONAdapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Foundation

struct JSONAdapter: RequestAdapter {
func adapt(_ urlRequest: URLRequest) -> URLRequest {
var request = urlRequest
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
return request
}
}
12 changes: 12 additions & 0 deletions ios/RocketChat Watch App/Client/Adapters/RequestAdapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Foundation

protocol RequestAdapter {
func adapt(_ urlRequest: URLRequest) -> URLRequest
func adapt(_ url: URL) -> URL
}

extension RequestAdapter {
func adapt(_ url: URL) -> URL {
url
}
}
25 changes: 25 additions & 0 deletions ios/RocketChat Watch App/Client/Adapters/TokenAdapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Foundation

struct TokenAdapter: RequestAdapter {
private let server: Server

init(server: Server) {
self.server = server
}

func adapt(_ url: URL) -> URL {
url.appending(
queryItems: [
URLQueryItem(name: "rc_token", value: server.loggedUser.token),
URLQueryItem(name: "rc_uid", value: server.loggedUser.id)
]
)
}

func adapt(_ urlRequest: URLRequest) -> URLRequest {
var request = urlRequest
request.addValue(server.loggedUser.id, forHTTPHeaderField: "x-user-id")
request.addValue(server.loggedUser.token, forHTTPHeaderField: "x-auth-token")
return request
}
}
44 changes: 44 additions & 0 deletions ios/RocketChat Watch App/Client/DateCodingStrategy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// https://stackoverflow.com/a/28016692

import Foundation

extension Date.ISO8601FormatStyle {
static let iso8601withFractionalSeconds: Self = .init(includingFractionalSeconds: true)
}

extension ParseStrategy where Self == Date.ISO8601FormatStyle {
static var iso8601withFractionalSeconds: Date.ISO8601FormatStyle { .iso8601withFractionalSeconds }
}

extension FormatStyle where Self == Date.ISO8601FormatStyle {
static var iso8601withFractionalSeconds: Date.ISO8601FormatStyle { .iso8601withFractionalSeconds }
}

extension Date {
init(iso8601withFractionalSeconds parseInput: ParseStrategy.ParseInput) throws {
try self.init(parseInput, strategy: .iso8601withFractionalSeconds)
}

var iso8601withFractionalSeconds: String {
formatted(.iso8601withFractionalSeconds)
}
}

extension String {
func iso8601withFractionalSeconds() throws -> Date {
try .init(iso8601withFractionalSeconds: self)
}
}

extension JSONDecoder.DateDecodingStrategy {
static let iso8601withFractionalSeconds = custom {
try .init(iso8601withFractionalSeconds: $0.singleValueContainer().decode(String.self))
}
}

extension JSONEncoder.DateEncodingStrategy {
static let iso8601withFractionalSeconds = custom {
var container = $1.singleValueContainer()
try container.encode($0.iso8601withFractionalSeconds)
}
}
Loading