mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Introduced MemberDetailsProvider, caching user avatar urls and images. Various other tweaks and improvements.
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
182BC48127C4EBBB00A30C33 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 182BC48027C4EBBB00A30C33 /* Kingfisher */; };
|
182BC48127C4EBBB00A30C33 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 182BC48027C4EBBB00A30C33 /* Kingfisher */; };
|
||||||
|
183E023227E4A3CF00903BED /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183E023127E4A3CF00903BED /* PlaceholderAvatarImage.swift */; };
|
||||||
184B31DF27D898960075A669 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 184B31DE27D898960075A669 /* Introspect */; };
|
184B31DF27D898960075A669 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 184B31DE27D898960075A669 /* Introspect */; };
|
||||||
1850253F27B6918D002E6B18 /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1850253E27B6918D002E6B18 /* ElementXTests.swift */; };
|
1850253F27B6918D002E6B18 /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1850253E27B6918D002E6B18 /* ElementXTests.swift */; };
|
||||||
1850254927B6918D002E6B18 /* ElementXUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1850254827B6918D002E6B18 /* ElementXUITests.swift */; };
|
1850254927B6918D002E6B18 /* ElementXUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1850254827B6918D002E6B18 /* ElementXUITests.swift */; };
|
||||||
@@ -18,7 +19,6 @@
|
|||||||
1850257127B6A135002E6B18 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1850256927B6A135002E6B18 /* LaunchScreen.storyboard */; };
|
1850257127B6A135002E6B18 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1850256927B6A135002E6B18 /* LaunchScreen.storyboard */; };
|
||||||
1863A3FC27BA5A9100B52E4D /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 1863A3FB27BA5A9100B52E4D /* KeychainAccess */; };
|
1863A3FC27BA5A9100B52E4D /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 1863A3FB27BA5A9100B52E4D /* KeychainAccess */; };
|
||||||
1863A40627BA6DFC00B52E4D /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = 1863A40527BA6DFC00B52E4D /* SwiftyBeaver */; };
|
1863A40627BA6DFC00B52E4D /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = 1863A40527BA6DFC00B52E4D /* SwiftyBeaver */; };
|
||||||
18A318DD27DA42C9000867CD /* RoomTimelineViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A318DB27DA42C9000867CD /* RoomTimelineViewProvider.swift */; };
|
|
||||||
18C5744627E11F1900D70937 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 18C5744527E11F1900D70937 /* MatrixRustSDK */; };
|
18C5744627E11F1900D70937 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 18C5744527E11F1900D70937 /* MatrixRustSDK */; };
|
||||||
18C5744C27E1D84000D70937 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5744827E1D84000D70937 /* RoomProxyProtocol.swift */; };
|
18C5744C27E1D84000D70937 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5744827E1D84000D70937 /* RoomProxyProtocol.swift */; };
|
||||||
18C5744D27E1D84000D70937 /* RoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5744A27E1D84000D70937 /* RoomProxy.swift */; };
|
18C5744D27E1D84000D70937 /* RoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5744A27E1D84000D70937 /* RoomProxy.swift */; };
|
||||||
@@ -27,12 +27,23 @@
|
|||||||
18C5745227E1D88600D70937 /* ImageRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5745127E1D88600D70937 /* ImageRoomMessage.swift */; };
|
18C5745227E1D88600D70937 /* ImageRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5745127E1D88600D70937 /* ImageRoomMessage.swift */; };
|
||||||
18C5745427E1D88E00D70937 /* TextRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5745327E1D88E00D70937 /* TextRoomMessage.swift */; };
|
18C5745427E1D88E00D70937 /* TextRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5745327E1D88E00D70937 /* TextRoomMessage.swift */; };
|
||||||
18C5745627E1DCA800D70937 /* RoomMessageFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5745527E1DCA800D70937 /* RoomMessageFactory.swift */; };
|
18C5745627E1DCA800D70937 /* RoomMessageFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5745527E1DCA800D70937 /* RoomMessageFactory.swift */; };
|
||||||
18C5745827E1EB6E00D70937 /* RoomTimelineItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18C5745727E1EB6E00D70937 /* RoomTimelineItemFactory.swift */; };
|
|
||||||
18DF7C2A27E23E3A00291672 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C2927E23E3A00291672 /* RoomTimelineItemProtocol.swift */; };
|
|
||||||
18DF7C2C27E23EC000291672 /* RoomTimelineViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C2B27E23EC000291672 /* RoomTimelineViewFactory.swift */; };
|
|
||||||
18DF7C2F27E264FC00291672 /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C2E27E264FC00291672 /* MediaProvider.swift */; };
|
18DF7C2F27E264FC00291672 /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C2E27E264FC00291672 /* MediaProvider.swift */; };
|
||||||
18DF7C3127E3608100291672 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3027E3608100291672 /* MediaProviderProtocol.swift */; };
|
18DF7C3127E3608100291672 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3027E3608100291672 /* MediaProviderProtocol.swift */; };
|
||||||
18DF7C3327E3608800291672 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3227E3608800291672 /* MockMediaProvider.swift */; };
|
18DF7C3327E3608800291672 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3227E3608800291672 /* MockMediaProvider.swift */; };
|
||||||
|
18DF7C4127E4670600291672 /* RoomTimelineViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3527E4670600291672 /* RoomTimelineViewProvider.swift */; };
|
||||||
|
18DF7C4227E4670600291672 /* RoomTimelineItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3627E4670600291672 /* RoomTimelineItemFactory.swift */; };
|
||||||
|
18DF7C4327E4670600291672 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3727E4670600291672 /* RoomTimelineItemProtocol.swift */; };
|
||||||
|
18DF7C4427E4670600291672 /* RoomTimelineViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3827E4670600291672 /* RoomTimelineViewFactory.swift */; };
|
||||||
|
18DF7C4527E4670600291672 /* SeparatorRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3A27E4670600291672 /* SeparatorRoomTimelineItem.swift */; };
|
||||||
|
18DF7C4627E4670600291672 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3B27E4670600291672 /* ImageRoomTimelineItem.swift */; };
|
||||||
|
18DF7C4727E4670600291672 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3C27E4670600291672 /* TextRoomTimelineItem.swift */; };
|
||||||
|
18DF7C4827E4670600291672 /* ImageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3E27E4670600291672 /* ImageRoomTimelineView.swift */; };
|
||||||
|
18DF7C4927E4670600291672 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C3F27E4670600291672 /* SeparatorRoomTimelineView.swift */; };
|
||||||
|
18DF7C4A27E4670600291672 /* TextRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C4027E4670600291672 /* TextRoomTimelineView.swift */; };
|
||||||
|
18DF7C4C27E4672C00291672 /* EventBasedTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C4B27E4672C00291672 /* EventBasedTimelineItemProtocol.swift */; };
|
||||||
|
18DF7C4E27E4673E00291672 /* DecorationTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C4D27E4673E00291672 /* DecorationTimelineItemProtocol.swift */; };
|
||||||
|
18DF7C5027E46A7A00291672 /* EventBasedTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C4F27E46A7A00291672 /* EventBasedTimelineView.swift */; };
|
||||||
|
18DF7C5327E4754500291672 /* MemberDetailsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DF7C5227E4754500291672 /* MemberDetailsProvider.swift */; };
|
||||||
18F2BADA27D25B4000DD1988 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BA7727D25B4000DD1988 /* RoomTimelineProvider.swift */; };
|
18F2BADA27D25B4000DD1988 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BA7727D25B4000DD1988 /* RoomTimelineProvider.swift */; };
|
||||||
18F2BADB27D25B4000DD1988 /* AuthenticationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BA7927D25B4000DD1988 /* AuthenticationCoordinator.swift */; };
|
18F2BADB27D25B4000DD1988 /* AuthenticationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BA7927D25B4000DD1988 /* AuthenticationCoordinator.swift */; };
|
||||||
18F2BADC27D25B4000DD1988 /* UserSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BA7A27D25B4000DD1988 /* UserSession.swift */; };
|
18F2BADC27D25B4000DD1988 /* UserSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BA7A27D25B4000DD1988 /* UserSession.swift */; };
|
||||||
@@ -90,12 +101,6 @@
|
|||||||
18F2BB2227D25D4600DD1988 /* LoginScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BACF27D25B4000DD1988 /* LoginScreenUITests.swift */; };
|
18F2BB2227D25D4600DD1988 /* LoginScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BACF27D25B4000DD1988 /* LoginScreenUITests.swift */; };
|
||||||
18F2BB2827D2647A00DD1988 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BB2727D2647A00DD1988 /* MockRoomTimelineController.swift */; };
|
18F2BB2827D2647A00DD1988 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BB2727D2647A00DD1988 /* MockRoomTimelineController.swift */; };
|
||||||
18F2BB2A27D2648900DD1988 /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BB2927D2648900DD1988 /* RoomTimelineControllerProtocol.swift */; };
|
18F2BB2A27D2648900DD1988 /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2BB2927D2648900DD1988 /* RoomTimelineControllerProtocol.swift */; };
|
||||||
18F9889827DB7473002F48B4 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F9889727DB7473002F48B4 /* ImageRoomTimelineItem.swift */; };
|
|
||||||
18F9889A27DB747B002F48B4 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F9889927DB747B002F48B4 /* TextRoomTimelineItem.swift */; };
|
|
||||||
18F9889C27DB7491002F48B4 /* SeparatorRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F9889B27DB7491002F48B4 /* SeparatorRoomTimelineItem.swift */; };
|
|
||||||
18F9889E27DB752B002F48B4 /* ImageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F9889D27DB752B002F48B4 /* ImageRoomTimelineView.swift */; };
|
|
||||||
18F988A027DB7532002F48B4 /* TextRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F9889F27DB7532002F48B4 /* TextRoomTimelineView.swift */; };
|
|
||||||
18F988A227DB753B002F48B4 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F988A127DB753B002F48B4 /* SeparatorRoomTimelineView.swift */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -117,6 +122,7 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
181716DC27E11EF1002B8E3F /* matrix-rust-components-swift */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "matrix-rust-components-swift"; path = "../matrix-rust-components-swift"; sourceTree = "<group>"; };
|
181716DC27E11EF1002B8E3F /* matrix-rust-components-swift */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "matrix-rust-components-swift"; path = "../matrix-rust-components-swift"; sourceTree = "<group>"; };
|
||||||
|
183E023127E4A3CF00903BED /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PlaceholderAvatarImage.swift; path = ../../../../../../../../Desktop/PlaceholderAvatarImage.swift; sourceTree = "<group>"; };
|
||||||
1850252427B6918C002E6B18 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
1850252427B6918C002E6B18 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
1850253A27B6918D002E6B18 /* ElementXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ElementXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
1850253A27B6918D002E6B18 /* ElementXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ElementXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
1850253E27B6918D002E6B18 /* ElementXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXTests.swift; sourceTree = "<group>"; };
|
1850253E27B6918D002E6B18 /* ElementXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXTests.swift; sourceTree = "<group>"; };
|
||||||
@@ -128,7 +134,6 @@
|
|||||||
1850256727B6A135002E6B18 /* ElementX.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = ElementX.entitlements; sourceTree = "<group>"; };
|
1850256727B6A135002E6B18 /* ElementX.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = ElementX.entitlements; sourceTree = "<group>"; };
|
||||||
1850256827B6A135002E6B18 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
1850256827B6A135002E6B18 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
1850256A27B6A135002E6B18 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
1850256A27B6A135002E6B18 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
18A318DB27DA42C9000867CD /* RoomTimelineViewProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewProvider.swift; sourceTree = "<group>"; };
|
|
||||||
18C5744827E1D84000D70937 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = "<group>"; };
|
18C5744827E1D84000D70937 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = "<group>"; };
|
||||||
18C5744A27E1D84000D70937 /* RoomProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomProxy.swift; sourceTree = "<group>"; };
|
18C5744A27E1D84000D70937 /* RoomProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomProxy.swift; sourceTree = "<group>"; };
|
||||||
18C5744B27E1D84000D70937 /* MockRoomProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockRoomProxy.swift; sourceTree = "<group>"; };
|
18C5744B27E1D84000D70937 /* MockRoomProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockRoomProxy.swift; sourceTree = "<group>"; };
|
||||||
@@ -136,12 +141,23 @@
|
|||||||
18C5745127E1D88600D70937 /* ImageRoomMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomMessage.swift; sourceTree = "<group>"; };
|
18C5745127E1D88600D70937 /* ImageRoomMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomMessage.swift; sourceTree = "<group>"; };
|
||||||
18C5745327E1D88E00D70937 /* TextRoomMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomMessage.swift; sourceTree = "<group>"; };
|
18C5745327E1D88E00D70937 /* TextRoomMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomMessage.swift; sourceTree = "<group>"; };
|
||||||
18C5745527E1DCA800D70937 /* RoomMessageFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageFactory.swift; sourceTree = "<group>"; };
|
18C5745527E1DCA800D70937 /* RoomMessageFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageFactory.swift; sourceTree = "<group>"; };
|
||||||
18C5745727E1EB6E00D70937 /* RoomTimelineItemFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactory.swift; sourceTree = "<group>"; };
|
|
||||||
18DF7C2927E23E3A00291672 /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
|
||||||
18DF7C2B27E23EC000291672 /* RoomTimelineViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewFactory.swift; sourceTree = "<group>"; };
|
|
||||||
18DF7C2E27E264FC00291672 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = "<group>"; };
|
18DF7C2E27E264FC00291672 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = "<group>"; };
|
||||||
18DF7C3027E3608100291672 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = "<group>"; };
|
18DF7C3027E3608100291672 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = "<group>"; };
|
||||||
18DF7C3227E3608800291672 /* MockMediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaProvider.swift; sourceTree = "<group>"; };
|
18DF7C3227E3608800291672 /* MockMediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaProvider.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3527E4670600291672 /* RoomTimelineViewProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewProvider.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3627E4670600291672 /* RoomTimelineItemFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactory.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3727E4670600291672 /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3827E4670600291672 /* RoomTimelineViewFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewFactory.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3A27E4670600291672 /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3B27E4670600291672 /* ImageRoomTimelineItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3C27E4670600291672 /* TextRoomTimelineItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3E27E4670600291672 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C3F27E4670600291672 /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C4027E4670600291672 /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C4B27E4672C00291672 /* EventBasedTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C4D27E4673E00291672 /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C4F27E46A7A00291672 /* EventBasedTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedTimelineView.swift; sourceTree = "<group>"; };
|
||||||
|
18DF7C5227E4754500291672 /* MemberDetailsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberDetailsProvider.swift; sourceTree = "<group>"; };
|
||||||
18F2BA7727D25B4000DD1988 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
|
18F2BA7727D25B4000DD1988 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
|
||||||
18F2BA7927D25B4000DD1988 /* AuthenticationCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinator.swift; sourceTree = "<group>"; };
|
18F2BA7927D25B4000DD1988 /* AuthenticationCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinator.swift; sourceTree = "<group>"; };
|
||||||
18F2BA7A27D25B4000DD1988 /* UserSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserSession.swift; sourceTree = "<group>"; };
|
18F2BA7A27D25B4000DD1988 /* UserSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserSession.swift; sourceTree = "<group>"; };
|
||||||
@@ -199,12 +215,6 @@
|
|||||||
18F2BB1927D25BE800DD1988 /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = "<group>"; };
|
18F2BB1927D25BE800DD1988 /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = "<group>"; };
|
||||||
18F2BB2727D2647A00DD1988 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = "<group>"; };
|
18F2BB2727D2647A00DD1988 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = "<group>"; };
|
||||||
18F2BB2927D2648900DD1988 /* RoomTimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerProtocol.swift; sourceTree = "<group>"; };
|
18F2BB2927D2648900DD1988 /* RoomTimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerProtocol.swift; sourceTree = "<group>"; };
|
||||||
18F9889727DB7473002F48B4 /* ImageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineItem.swift; sourceTree = "<group>"; };
|
|
||||||
18F9889927DB747B002F48B4 /* TextRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItem.swift; sourceTree = "<group>"; };
|
|
||||||
18F9889B27DB7491002F48B4 /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
|
||||||
18F9889D27DB752B002F48B4 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
|
|
||||||
18F9889F27DB7532002F48B4 /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = "<group>"; };
|
|
||||||
18F988A127DB753B002F48B4 /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = "<group>"; };
|
|
||||||
18FE279627C7B85300016375 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
18FE279627C7B85300016375 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@@ -309,23 +319,6 @@
|
|||||||
path = "Supporting Files";
|
path = "Supporting Files";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
18A318D927DA42C9000867CD /* TimelineItems */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
18DF7C2927E23E3A00291672 /* RoomTimelineItemProtocol.swift */,
|
|
||||||
18C5745727E1EB6E00D70937 /* RoomTimelineItemFactory.swift */,
|
|
||||||
18DF7C2B27E23EC000291672 /* RoomTimelineViewFactory.swift */,
|
|
||||||
18A318DB27DA42C9000867CD /* RoomTimelineViewProvider.swift */,
|
|
||||||
18F9889727DB7473002F48B4 /* ImageRoomTimelineItem.swift */,
|
|
||||||
18F9889D27DB752B002F48B4 /* ImageRoomTimelineView.swift */,
|
|
||||||
18F9889927DB747B002F48B4 /* TextRoomTimelineItem.swift */,
|
|
||||||
18F9889F27DB7532002F48B4 /* TextRoomTimelineView.swift */,
|
|
||||||
18F9889B27DB7491002F48B4 /* SeparatorRoomTimelineItem.swift */,
|
|
||||||
18F988A127DB753B002F48B4 /* SeparatorRoomTimelineView.swift */,
|
|
||||||
);
|
|
||||||
path = TimelineItems;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
18C5744427E11F1900D70937 /* Frameworks */ = {
|
18C5744427E11F1900D70937 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -336,6 +329,7 @@
|
|||||||
18C5744727E1D84000D70937 /* Room */ = {
|
18C5744727E1D84000D70937 /* Room */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
18DF7C5127E4753A00291672 /* Members */,
|
||||||
18C5744927E1D84000D70937 /* Messages */,
|
18C5744927E1D84000D70937 /* Messages */,
|
||||||
18C5744827E1D84000D70937 /* RoomProxyProtocol.swift */,
|
18C5744827E1D84000D70937 /* RoomProxyProtocol.swift */,
|
||||||
18C5744A27E1D84000D70937 /* RoomProxy.swift */,
|
18C5744A27E1D84000D70937 /* RoomProxy.swift */,
|
||||||
@@ -365,6 +359,51 @@
|
|||||||
path = Media;
|
path = Media;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
18DF7C3427E4670600291672 /* TimelineItems */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
18DF7C3627E4670600291672 /* RoomTimelineItemFactory.swift */,
|
||||||
|
18DF7C3827E4670600291672 /* RoomTimelineViewFactory.swift */,
|
||||||
|
18DF7C3527E4670600291672 /* RoomTimelineViewProvider.swift */,
|
||||||
|
18DF7C3727E4670600291672 /* RoomTimelineItemProtocol.swift */,
|
||||||
|
18DF7C4B27E4672C00291672 /* EventBasedTimelineItemProtocol.swift */,
|
||||||
|
18DF7C4D27E4673E00291672 /* DecorationTimelineItemProtocol.swift */,
|
||||||
|
18DF7C3927E4670600291672 /* Items */,
|
||||||
|
18DF7C3D27E4670600291672 /* Views */,
|
||||||
|
);
|
||||||
|
path = TimelineItems;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
18DF7C3927E4670600291672 /* Items */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
18DF7C3A27E4670600291672 /* SeparatorRoomTimelineItem.swift */,
|
||||||
|
18DF7C3B27E4670600291672 /* ImageRoomTimelineItem.swift */,
|
||||||
|
18DF7C3C27E4670600291672 /* TextRoomTimelineItem.swift */,
|
||||||
|
);
|
||||||
|
path = Items;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
18DF7C3D27E4670600291672 /* Views */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
183E023127E4A3CF00903BED /* PlaceholderAvatarImage.swift */,
|
||||||
|
18DF7C4F27E46A7A00291672 /* EventBasedTimelineView.swift */,
|
||||||
|
18DF7C4027E4670600291672 /* TextRoomTimelineView.swift */,
|
||||||
|
18DF7C3E27E4670600291672 /* ImageRoomTimelineView.swift */,
|
||||||
|
18DF7C3F27E4670600291672 /* SeparatorRoomTimelineView.swift */,
|
||||||
|
);
|
||||||
|
path = Views;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
18DF7C5127E4753A00291672 /* Members */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
18DF7C5227E4754500291672 /* MemberDetailsProvider.swift */,
|
||||||
|
);
|
||||||
|
path = Members;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
18F2BA7227D25B4000DD1988 /* Services */ = {
|
18F2BA7227D25B4000DD1988 /* Services */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -383,7 +422,7 @@
|
|||||||
18F2BB1927D25BE800DD1988 /* RoomTimelineController.swift */,
|
18F2BB1927D25BE800DD1988 /* RoomTimelineController.swift */,
|
||||||
18F2BB2727D2647A00DD1988 /* MockRoomTimelineController.swift */,
|
18F2BB2727D2647A00DD1988 /* MockRoomTimelineController.swift */,
|
||||||
18F2BA7727D25B4000DD1988 /* RoomTimelineProvider.swift */,
|
18F2BA7727D25B4000DD1988 /* RoomTimelineProvider.swift */,
|
||||||
18A318D927DA42C9000867CD /* TimelineItems */,
|
18DF7C3427E4670600291672 /* TimelineItems */,
|
||||||
);
|
);
|
||||||
path = Timeline;
|
path = Timeline;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -814,24 +853,28 @@
|
|||||||
files = (
|
files = (
|
||||||
18F2BADE27D25B4000DD1988 /* KeychainControllerProtocol.swift in Sources */,
|
18F2BADE27D25B4000DD1988 /* KeychainControllerProtocol.swift in Sources */,
|
||||||
18C5745027E1D87800D70937 /* RoomMessageProtocol.swift in Sources */,
|
18C5745027E1D87800D70937 /* RoomMessageProtocol.swift in Sources */,
|
||||||
|
18DF7C4C27E4672C00291672 /* EventBasedTimelineItemProtocol.swift in Sources */,
|
||||||
18F2BAED27D25B4000DD1988 /* FullscreenLoadingActivityPresenter.swift in Sources */,
|
18F2BAED27D25B4000DD1988 /* FullscreenLoadingActivityPresenter.swift in Sources */,
|
||||||
|
18DF7C4127E4670600291672 /* RoomTimelineViewProvider.swift in Sources */,
|
||||||
18F2BB0F27D25B4000DD1988 /* RoomScreen.swift in Sources */,
|
18F2BB0F27D25B4000DD1988 /* RoomScreen.swift in Sources */,
|
||||||
18F2BAFF27D25B4000DD1988 /* HomeScreenModels.swift in Sources */,
|
18F2BAFF27D25B4000DD1988 /* HomeScreenModels.swift in Sources */,
|
||||||
18F9889C27DB7491002F48B4 /* SeparatorRoomTimelineItem.swift in Sources */,
|
18DF7C4E27E4673E00291672 /* DecorationTimelineItemProtocol.swift in Sources */,
|
||||||
18F2BB1527D25B4000DD1988 /* LoginScreenViewModelProtocol.swift in Sources */,
|
18F2BB1527D25B4000DD1988 /* LoginScreenViewModelProtocol.swift in Sources */,
|
||||||
18F2BAEB27D25B4000DD1988 /* LabelledActivityIndicatorView.swift in Sources */,
|
18F2BAEB27D25B4000DD1988 /* LabelledActivityIndicatorView.swift in Sources */,
|
||||||
18F2BAE427D25B4000DD1988 /* Presentable.swift in Sources */,
|
18F2BAE427D25B4000DD1988 /* Presentable.swift in Sources */,
|
||||||
18DF7C2A27E23E3A00291672 /* RoomTimelineItemProtocol.swift in Sources */,
|
18DF7C4427E4670600291672 /* RoomTimelineViewFactory.swift in Sources */,
|
||||||
|
183E023227E4A3CF00903BED /* PlaceholderAvatarImage.swift in Sources */,
|
||||||
18F2BAF927D25B4000DD1988 /* SplashViewController.swift in Sources */,
|
18F2BAF927D25B4000DD1988 /* SplashViewController.swift in Sources */,
|
||||||
18F2BAE327D25B4000DD1988 /* RootRouter.swift in Sources */,
|
18F2BAE327D25B4000DD1988 /* RootRouter.swift in Sources */,
|
||||||
18F2BAE527D25B4000DD1988 /* NavigationModule.swift in Sources */,
|
18F2BAE527D25B4000DD1988 /* NavigationModule.swift in Sources */,
|
||||||
18F2BB1227D25B4000DD1988 /* LoginScreenViewModel.swift in Sources */,
|
18F2BB1227D25B4000DD1988 /* LoginScreenViewModel.swift in Sources */,
|
||||||
18F2BAE727D25B4000DD1988 /* RoundedToastView.swift in Sources */,
|
18F2BAE727D25B4000DD1988 /* RoundedToastView.swift in Sources */,
|
||||||
18F2BAF227D25B4000DD1988 /* WeakDictionaryKeyReference.swift in Sources */,
|
18F2BAF227D25B4000DD1988 /* WeakDictionaryKeyReference.swift in Sources */,
|
||||||
18F988A027DB7532002F48B4 /* TextRoomTimelineView.swift in Sources */,
|
18DF7C4727E4670600291672 /* TextRoomTimelineItem.swift in Sources */,
|
||||||
18F2BAE027D25B4000DD1988 /* NavigationRouter.swift in Sources */,
|
18F2BAE027D25B4000DD1988 /* NavigationRouter.swift in Sources */,
|
||||||
18F2BAF627D25B4000DD1988 /* Coordinator.swift in Sources */,
|
18F2BAF627D25B4000DD1988 /* Coordinator.swift in Sources */,
|
||||||
18F2BAEA27D25B4000DD1988 /* ActivityCenter.swift in Sources */,
|
18F2BAEA27D25B4000DD1988 /* ActivityCenter.swift in Sources */,
|
||||||
|
18DF7C4827E4670600291672 /* ImageRoomTimelineView.swift in Sources */,
|
||||||
18F2BB1A27D25BE800DD1988 /* RoomTimelineController.swift in Sources */,
|
18F2BB1A27D25BE800DD1988 /* RoomTimelineController.swift in Sources */,
|
||||||
18F2BAF327D25B4000DD1988 /* WeakDictionaryReference.swift in Sources */,
|
18F2BAF327D25B4000DD1988 /* WeakDictionaryReference.swift in Sources */,
|
||||||
18F2BB2A27D2648900DD1988 /* RoomTimelineControllerProtocol.swift in Sources */,
|
18F2BB2A27D2648900DD1988 /* RoomTimelineControllerProtocol.swift in Sources */,
|
||||||
@@ -842,46 +885,47 @@
|
|||||||
18F2BB1127D25B4000DD1988 /* RoomScreenModels.swift in Sources */,
|
18F2BB1127D25B4000DD1988 /* RoomScreenModels.swift in Sources */,
|
||||||
18F2BADB27D25B4000DD1988 /* AuthenticationCoordinator.swift in Sources */,
|
18F2BADB27D25B4000DD1988 /* AuthenticationCoordinator.swift in Sources */,
|
||||||
1850256F27B6A135002E6B18 /* AppDelegate.swift in Sources */,
|
1850256F27B6A135002E6B18 /* AppDelegate.swift in Sources */,
|
||||||
|
18DF7C4927E4670600291672 /* SeparatorRoomTimelineView.swift in Sources */,
|
||||||
18F2BAE627D25B4000DD1988 /* NavigationRouterType.swift in Sources */,
|
18F2BAE627D25B4000DD1988 /* NavigationRouterType.swift in Sources */,
|
||||||
18F2BAE927D25B4000DD1988 /* ActivityPresentable.swift in Sources */,
|
18F2BAE927D25B4000DD1988 /* ActivityPresentable.swift in Sources */,
|
||||||
|
18DF7C4327E4670600291672 /* RoomTimelineItemProtocol.swift in Sources */,
|
||||||
18F2BAF827D25B4000DD1988 /* BindableState.swift in Sources */,
|
18F2BAF827D25B4000DD1988 /* BindableState.swift in Sources */,
|
||||||
18F2BB1827D25B4000DD1988 /* LoginScreen.swift in Sources */,
|
18F2BB1827D25B4000DD1988 /* LoginScreen.swift in Sources */,
|
||||||
|
18DF7C5327E4754500291672 /* MemberDetailsProvider.swift in Sources */,
|
||||||
18F2BAE227D25B4000DD1988 /* NavigationRouterStoreProtocol.swift in Sources */,
|
18F2BAE227D25B4000DD1988 /* NavigationRouterStoreProtocol.swift in Sources */,
|
||||||
18F2BB1727D25B4000DD1988 /* LoginScreenCoordinator.swift in Sources */,
|
18F2BB1727D25B4000DD1988 /* LoginScreenCoordinator.swift in Sources */,
|
||||||
18F2BAF527D25B4000DD1988 /* WeakKeyDictionary.swift in Sources */,
|
18F2BAF527D25B4000DD1988 /* WeakKeyDictionary.swift in Sources */,
|
||||||
18F2BADF27D25B4000DD1988 /* NavigationRouterStore.swift in Sources */,
|
18F2BADF27D25B4000DD1988 /* NavigationRouterStore.swift in Sources */,
|
||||||
18F2BAFE27D25B4000DD1988 /* HomeScreenViewModelProtocol.swift in Sources */,
|
18F2BAFE27D25B4000DD1988 /* HomeScreenViewModelProtocol.swift in Sources */,
|
||||||
18DF7C3327E3608800291672 /* MockMediaProvider.swift in Sources */,
|
18DF7C3327E3608800291672 /* MockMediaProvider.swift in Sources */,
|
||||||
|
18DF7C4627E4670600291672 /* ImageRoomTimelineItem.swift in Sources */,
|
||||||
18F2BAE827D25B4000DD1988 /* RectangleToastView.swift in Sources */,
|
18F2BAE827D25B4000DD1988 /* RectangleToastView.swift in Sources */,
|
||||||
18F2BB1627D25B4000DD1988 /* LoginScreenModels.swift in Sources */,
|
18F2BB1627D25B4000DD1988 /* LoginScreenModels.swift in Sources */,
|
||||||
18F9889E27DB752B002F48B4 /* ImageRoomTimelineView.swift in Sources */,
|
|
||||||
18F2BADA27D25B4000DD1988 /* RoomTimelineProvider.swift in Sources */,
|
18F2BADA27D25B4000DD1988 /* RoomTimelineProvider.swift in Sources */,
|
||||||
18DF7C2F27E264FC00291672 /* MediaProvider.swift in Sources */,
|
18DF7C2F27E264FC00291672 /* MediaProvider.swift in Sources */,
|
||||||
18C5744D27E1D84000D70937 /* RoomProxy.swift in Sources */,
|
18C5744D27E1D84000D70937 /* RoomProxy.swift in Sources */,
|
||||||
18F9889827DB7473002F48B4 /* ImageRoomTimelineItem.swift in Sources */,
|
|
||||||
18F2BB0027D25B4000DD1988 /* HomeScreen.swift in Sources */,
|
18F2BB0027D25B4000DD1988 /* HomeScreen.swift in Sources */,
|
||||||
18F2BB2827D2647A00DD1988 /* MockRoomTimelineController.swift in Sources */,
|
18F2BB2827D2647A00DD1988 /* MockRoomTimelineController.swift in Sources */,
|
||||||
18DF7C3127E3608100291672 /* MediaProviderProtocol.swift in Sources */,
|
18DF7C3127E3608100291672 /* MediaProviderProtocol.swift in Sources */,
|
||||||
18F2BB0127D25B4000DD1988 /* HomeScreenViewModel.swift in Sources */,
|
18F2BB0127D25B4000DD1988 /* HomeScreenViewModel.swift in Sources */,
|
||||||
18F2BAF027D25B4000DD1988 /* ActivityDismissal.swift in Sources */,
|
18F2BAF027D25B4000DD1988 /* ActivityDismissal.swift in Sources */,
|
||||||
18F2BADD27D25B4000DD1988 /* KeychainController.swift in Sources */,
|
18F2BADD27D25B4000DD1988 /* KeychainController.swift in Sources */,
|
||||||
18A318DD27DA42C9000867CD /* RoomTimelineViewProvider.swift in Sources */,
|
|
||||||
18F2BAFB27D25B4000DD1988 /* HomeScreenCoordinator.swift in Sources */,
|
18F2BAFB27D25B4000DD1988 /* HomeScreenCoordinator.swift in Sources */,
|
||||||
18F2BB0C27D25B4000DD1988 /* RoomScreenCoordinator.swift in Sources */,
|
18F2BB0C27D25B4000DD1988 /* RoomScreenCoordinator.swift in Sources */,
|
||||||
|
18DF7C5027E46A7A00291672 /* EventBasedTimelineView.swift in Sources */,
|
||||||
|
18DF7C4A27E4670600291672 /* TextRoomTimelineView.swift in Sources */,
|
||||||
|
18DF7C4527E4670600291672 /* SeparatorRoomTimelineItem.swift in Sources */,
|
||||||
|
18DF7C4227E4670600291672 /* RoomTimelineItemFactory.swift in Sources */,
|
||||||
18F2BB0E27D25B4000DD1988 /* RoomScreenViewModelProtocol.swift in Sources */,
|
18F2BB0E27D25B4000DD1988 /* RoomScreenViewModelProtocol.swift in Sources */,
|
||||||
18F2BB0D27D25B4000DD1988 /* RoomScreenViewModel.swift in Sources */,
|
18F2BB0D27D25B4000DD1988 /* RoomScreenViewModel.swift in Sources */,
|
||||||
18F988A227DB753B002F48B4 /* SeparatorRoomTimelineView.swift in Sources */,
|
|
||||||
18C5745427E1D88E00D70937 /* TextRoomMessage.swift in Sources */,
|
18C5745427E1D88E00D70937 /* TextRoomMessage.swift in Sources */,
|
||||||
18C5745227E1D88600D70937 /* ImageRoomMessage.swift in Sources */,
|
18C5745227E1D88600D70937 /* ImageRoomMessage.swift in Sources */,
|
||||||
18F2BAE127D25B4000DD1988 /* RootRouterType.swift in Sources */,
|
18F2BAE127D25B4000DD1988 /* RootRouterType.swift in Sources */,
|
||||||
1850256C27B6A135002E6B18 /* AppCoordinator.swift in Sources */,
|
1850256C27B6A135002E6B18 /* AppCoordinator.swift in Sources */,
|
||||||
18F9889A27DB747B002F48B4 /* TextRoomTimelineItem.swift in Sources */,
|
|
||||||
18C5744C27E1D84000D70937 /* RoomProxyProtocol.swift in Sources */,
|
18C5744C27E1D84000D70937 /* RoomProxyProtocol.swift in Sources */,
|
||||||
18C5744E27E1D84000D70937 /* MockRoomProxy.swift in Sources */,
|
18C5744E27E1D84000D70937 /* MockRoomProxy.swift in Sources */,
|
||||||
18F2BADC27D25B4000DD1988 /* UserSession.swift in Sources */,
|
18F2BADC27D25B4000DD1988 /* UserSession.swift in Sources */,
|
||||||
18F2BAEF27D25B4000DD1988 /* ActivityRequest.swift in Sources */,
|
18F2BAEF27D25B4000DD1988 /* ActivityRequest.swift in Sources */,
|
||||||
18DF7C2C27E23EC000291672 /* RoomTimelineViewFactory.swift in Sources */,
|
|
||||||
18C5745827E1EB6E00D70937 /* RoomTimelineItemFactory.swift in Sources */,
|
|
||||||
18F2BAEE27D25B4000DD1988 /* Activity.swift in Sources */,
|
18F2BAEE27D25B4000DD1988 /* Activity.swift in Sources */,
|
||||||
18F2BAEC27D25B4000DD1988 /* ToastActivityPresenter.swift in Sources */,
|
18F2BAEC27D25B4000DD1988 /* ToastActivityPresenter.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -113,7 +113,18 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let parameters = RoomScreenCoordinatorParameters(roomProxy: roomProxy, mediaProvider: userSession.mediaProvider)
|
let memberDetailsProvider = MemberDetailsProvider(roomProxy: roomProxy)
|
||||||
|
|
||||||
|
let timelineItemFactory = RoomTimelineItemFactory(mediaProvider: userSession.mediaProvider,
|
||||||
|
memberDetailsProvider: memberDetailsProvider)
|
||||||
|
|
||||||
|
let timelineController = RoomTimelineController(timelineProvider: RoomTimelineProvider(roomProxy: roomProxy),
|
||||||
|
timelineItemFactory: timelineItemFactory,
|
||||||
|
mediaProvider: userSession.mediaProvider,
|
||||||
|
memberDetailsProvider: memberDetailsProvider)
|
||||||
|
|
||||||
|
let parameters = RoomScreenCoordinatorParameters(timelineController: timelineController,
|
||||||
|
roomName: roomProxy.name)
|
||||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||||
|
|
||||||
self.add(childCoordinator: coordinator)
|
self.add(childCoordinator: coordinator)
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct RoomScreenCoordinatorParameters {
|
struct RoomScreenCoordinatorParameters {
|
||||||
let roomProxy: RoomProxyProtocol
|
let timelineController: RoomTimelineControllerProtocol
|
||||||
let mediaProvider: MediaProviderProtocol
|
let roomName: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
final class RoomScreenCoordinator: Coordinator, Presentable {
|
final class RoomScreenCoordinator: Coordinator, Presentable {
|
||||||
@@ -42,14 +42,10 @@ final class RoomScreenCoordinator: Coordinator, Presentable {
|
|||||||
init(parameters: RoomScreenCoordinatorParameters) {
|
init(parameters: RoomScreenCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
|
|
||||||
let timelineProvider = RoomTimelineProvider(roomProxy: parameters.roomProxy)
|
let viewModel = RoomScreenViewModel(timelineController: parameters.timelineController,
|
||||||
let timelineController = RoomTimelineController(timelineProvider: timelineProvider,
|
timelineViewFactory: RoomTimelineViewFactory(),
|
||||||
timelineItemFactory: RoomTimelineItemFactory(mediaProvider: parameters.mediaProvider),
|
roomName: parameters.roomName)
|
||||||
mediaProvider: parameters.mediaProvider)
|
|
||||||
|
|
||||||
let viewModel = RoomScreenViewModel(roomProxy: parameters.roomProxy,
|
|
||||||
timelineController: timelineController,
|
|
||||||
timelineViewFactory: RoomTimelineViewFactory())
|
|
||||||
let view = RoomScreen(context: viewModel.context)
|
let view = RoomScreen(context: viewModel.context)
|
||||||
roomScreenViewModel = viewModel
|
roomScreenViewModel = viewModel
|
||||||
roomScreenHostingController = UIHostingController(rootView: view)
|
roomScreenHostingController = UIHostingController(rootView: view)
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import SwiftUI
|
|||||||
|
|
||||||
@available(iOS 14, *)
|
@available(iOS 14, *)
|
||||||
typealias RoomScreenViewModelType = StateStoreViewModel<RoomScreenViewState,
|
typealias RoomScreenViewModelType = StateStoreViewModel<RoomScreenViewState,
|
||||||
Never,
|
Never,
|
||||||
RoomScreenViewAction>
|
RoomScreenViewAction>
|
||||||
@available(iOS 14, *)
|
@available(iOS 14, *)
|
||||||
class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol {
|
class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol {
|
||||||
|
|
||||||
@@ -27,22 +27,19 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
static let backPaginationPageSize: UInt = 30
|
static let backPaginationPageSize: UInt = 30
|
||||||
}
|
}
|
||||||
|
|
||||||
private let roomProxy: RoomProxyProtocol
|
|
||||||
private let timelineController: RoomTimelineControllerProtocol
|
private let timelineController: RoomTimelineControllerProtocol
|
||||||
private let timelineViewFactory: RoomTimelineViewFactory
|
private let timelineViewFactory: RoomTimelineViewFactory
|
||||||
|
|
||||||
// MARK: - Setup
|
// MARK: - Setup
|
||||||
|
|
||||||
init(roomProxy: RoomProxyProtocol,
|
init(timelineController: RoomTimelineControllerProtocol,
|
||||||
timelineController: RoomTimelineControllerProtocol,
|
timelineViewFactory: RoomTimelineViewFactory,
|
||||||
timelineViewFactory: RoomTimelineViewFactory) {
|
roomName: String?) {
|
||||||
self.roomProxy = roomProxy
|
|
||||||
self.timelineController = timelineController
|
self.timelineController = timelineController
|
||||||
self.timelineViewFactory = timelineViewFactory
|
self.timelineViewFactory = timelineViewFactory
|
||||||
|
|
||||||
super.init(initialViewState: RoomScreenViewState())
|
super.init(initialViewState: RoomScreenViewState(roomTitle: roomName ?? "💥"))
|
||||||
|
|
||||||
state.roomTitle = roomProxy.name ?? ""
|
|
||||||
buildTimelineViews()
|
buildTimelineViews()
|
||||||
|
|
||||||
timelineController.callbacks.sink { [weak self] callback in
|
timelineController.callbacks.sink { [weak self] callback in
|
||||||
|
|||||||
@@ -240,9 +240,9 @@ private class TableViewObserver: NSObject, UITableViewDelegate {
|
|||||||
|
|
||||||
struct RoomScreen_Previews: PreviewProvider {
|
struct RoomScreen_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let viewModel = RoomScreenViewModel(roomProxy: MockRoomProxy(displayName: "Test"),
|
let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
|
||||||
timelineController: MockRoomTimelineController(),
|
timelineViewFactory: RoomTimelineViewFactory(),
|
||||||
timelineViewFactory: RoomTimelineViewFactory())
|
roomName: "Preview room")
|
||||||
|
|
||||||
RoomScreen(context: viewModel.context)
|
RoomScreen(context: viewModel.context)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,16 +13,18 @@ import Kingfisher
|
|||||||
struct MediaProvider: MediaProviderProtocol {
|
struct MediaProvider: MediaProviderProtocol {
|
||||||
private let client: Client
|
private let client: Client
|
||||||
private let imageCache: Kingfisher.ImageCache
|
private let imageCache: Kingfisher.ImageCache
|
||||||
|
private let processingQueue: DispatchQueue
|
||||||
|
|
||||||
init(client: Client, imageCache: Kingfisher.ImageCache) {
|
init(client: Client, imageCache: Kingfisher.ImageCache) {
|
||||||
self.client = client
|
self.client = client
|
||||||
self.imageCache = imageCache
|
self.imageCache = imageCache
|
||||||
|
self.processingQueue = DispatchQueue(label: "MediaProviderProcessingQueue")
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadCurrentUserAvatar(_ completion: @escaping (Result<UIImage?, MediaProviderError>) -> Void) {
|
func loadCurrentUserAvatar(_ completion: @escaping (Result<UIImage?, MediaProviderError>) -> Void) {
|
||||||
DispatchQueue.global(qos: .background).async {
|
processingQueue.async {
|
||||||
do {
|
do {
|
||||||
let imageData = try self.client.avatar()
|
let imageData = try client.avatar()
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
completion(.success(UIImage(data: Data(bytes: imageData, count: imageData.count))))
|
completion(.success(UIImage(data: Data(bytes: imageData, count: imageData.count))))
|
||||||
}
|
}
|
||||||
@@ -35,21 +37,25 @@ struct MediaProvider: MediaProviderProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasImageCachedForURL(_ url: String) -> Bool {
|
func imageForURL(_ url: String?) -> UIImage? {
|
||||||
self.imageCache.imageCachedType(forKey: url) == .memory
|
guard let url = url else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageCache.retrieveImageInMemoryCache(forKey: url, options: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadImageFromURL(_ url: String, _ completion: @escaping (Result<UIImage, MediaProviderError>) -> Void) {
|
func loadImageFromURL(_ url: String, _ completion: @escaping (Result<UIImage, MediaProviderError>) -> Void) {
|
||||||
self.imageCache.retrieveImage(forKey: url) { result in
|
imageCache.retrieveImage(forKey: url) { result in
|
||||||
if case let .success(cacheResult) = result,
|
if case let .success(cacheResult) = result,
|
||||||
let image = cacheResult.image {
|
let image = cacheResult.image {
|
||||||
completion(.success(image))
|
completion(.success(image))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DispatchQueue.global(qos: .background).async {
|
processingQueue.async {
|
||||||
do {
|
do {
|
||||||
let imageData = try self.client.loadImage(url: url)
|
let imageData = try client.loadImage(url: url)
|
||||||
|
|
||||||
guard let image = UIImage(data: Data(bytes: imageData, count: imageData.count)) else {
|
guard let image = UIImage(data: Data(bytes: imageData, count: imageData.count)) else {
|
||||||
MXLog.error("Invalid image data")
|
MXLog.error("Invalid image data")
|
||||||
@@ -59,7 +65,7 @@ struct MediaProvider: MediaProviderProtocol {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.imageCache.store(image, forKey: url)
|
imageCache.store(image, forKey: url)
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
completion(.success(image))
|
completion(.success(image))
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ enum MediaProviderError: Error {
|
|||||||
|
|
||||||
protocol MediaProviderProtocol {
|
protocol MediaProviderProtocol {
|
||||||
func loadCurrentUserAvatar(_ completion: @escaping (Result<UIImage?, MediaProviderError>) -> Void)
|
func loadCurrentUserAvatar(_ completion: @escaping (Result<UIImage?, MediaProviderError>) -> Void)
|
||||||
func hasImageCachedForURL(_ url: String) -> Bool
|
|
||||||
|
func imageForURL(_ url: String?) -> UIImage?
|
||||||
|
|
||||||
func loadImageFromURL(_ url: String, _ completion: @escaping (Result<UIImage, MediaProviderError>) -> Void)
|
func loadImageFromURL(_ url: String, _ completion: @escaping (Result<UIImage, MediaProviderError>) -> Void)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ struct MockMediaProvider: MediaProviderProtocol {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasImageCachedForURL(_ url: String) -> Bool {
|
func imageForURL(_ url: String?) -> UIImage? {
|
||||||
true
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadImageFromURL(_ url: String, _ completion: @escaping (Result<UIImage, MediaProviderError>) -> Void) {
|
func loadImageFromURL(_ url: String, _ completion: @escaping (Result<UIImage, MediaProviderError>) -> Void) {
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// MemberDetailsProvider.swift
|
||||||
|
// ElementX
|
||||||
|
//
|
||||||
|
// Created by Stefan Ceriu on 18/03/2022.
|
||||||
|
// Copyright © 2022 Element. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum MemberDetailsProviderError: Error {
|
||||||
|
case invalidRoomProxy
|
||||||
|
case failedRetrievingUserAvatarURL
|
||||||
|
}
|
||||||
|
|
||||||
|
class MemberDetailsProvider {
|
||||||
|
private let roomProxy: RoomProxyProtocol?
|
||||||
|
private let processingQueue = DispatchQueue(label: "MemberDetailsProviderProcessingQueue")
|
||||||
|
private var memberAvatars = [String: String]()
|
||||||
|
|
||||||
|
init(roomProxy: RoomProxyProtocol) {
|
||||||
|
self.roomProxy = roomProxy
|
||||||
|
}
|
||||||
|
|
||||||
|
func avatarURLForUserId(_ userId: String) -> String? {
|
||||||
|
self.memberAvatars[userId]
|
||||||
|
}
|
||||||
|
|
||||||
|
func avatarURLForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailsProviderError>) -> Void) {
|
||||||
|
guard let roomProxy = roomProxy else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let avatarURL = avatarURLForUserId(userId) {
|
||||||
|
completion(.success(avatarURL))
|
||||||
|
}
|
||||||
|
|
||||||
|
processingQueue.async {
|
||||||
|
roomProxy.avatarURLForUserId(userId, completion: { [weak self] result in
|
||||||
|
guard let self = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch result {
|
||||||
|
case .success(let avatarURL):
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.memberAvatars[userId] = avatarURL
|
||||||
|
completion(.success(avatarURL))
|
||||||
|
}
|
||||||
|
case .failure:
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
completion(.failure(.failedRetrievingUserAvatarURL))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -91,7 +91,7 @@ class RoomProxy: RoomProxyProtocol, Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func avatarURLForUserId(_ userId: String, completion: @escaping (Result<String?, RoomProxyError>) -> Void) {
|
func avatarURLForUserId(_ userId: String, completion: @escaping (Result<String?, RoomProxyError>) -> Void) {
|
||||||
DispatchQueue.global(qos: .background).async {
|
processingQueue.async {
|
||||||
do {
|
do {
|
||||||
let avatarURL = try self.room.memberAvatarUrl(userId: userId)
|
let avatarURL = try self.room.memberAvatarUrl(userId: userId)
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ class RoomProxy: RoomProxyProtocol, Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadDisplayName(_ completion: @escaping (Result<String, RoomProxyError>) -> Void) {
|
func loadDisplayName(_ completion: @escaping (Result<String, RoomProxyError>) -> Void) {
|
||||||
DispatchQueue.global(qos: .background).async {
|
processingQueue.async {
|
||||||
do {
|
do {
|
||||||
let displayName = try self.room.displayName()
|
let displayName = try self.room.displayName()
|
||||||
|
|
||||||
@@ -123,7 +123,6 @@ class RoomProxy: RoomProxyProtocol, Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func paginateBackwards(count: UInt, callback: ((Result<[RoomMessageProtocol], RoomProxyError>) -> Void)?) {
|
func paginateBackwards(count: UInt, callback: ((Result<[RoomMessageProtocol], RoomProxyError>) -> Void)?) {
|
||||||
MXLog.debug("Started backpaginating")
|
|
||||||
processingQueue.async {
|
processingQueue.async {
|
||||||
guard let backwardStream = self.backwardStream else {
|
guard let backwardStream = self.backwardStream else {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@@ -136,8 +135,6 @@ class RoomProxy: RoomProxyProtocol, Equatable {
|
|||||||
self.messageFactory.buildRoomMessageFrom(message)
|
self.messageFactory.buildRoomMessageFrom(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
MXLog.debug("Finished backpaginating")
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
callback?(.success(messages))
|
callback?(.success(messages))
|
||||||
if self.lastMessage == nil {
|
if self.lastMessage == nil {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
private let timelineProvider: RoomTimelineProvider
|
private let timelineProvider: RoomTimelineProvider
|
||||||
private let timelineItemFactory: RoomTimelineItemFactory
|
private let timelineItemFactory: RoomTimelineItemFactory
|
||||||
private let mediaProvider: MediaProviderProtocol
|
private let mediaProvider: MediaProviderProtocol
|
||||||
|
private let memberDetailsProvider: MemberDetailsProvider
|
||||||
|
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
@@ -22,10 +23,12 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
|
|
||||||
init(timelineProvider: RoomTimelineProvider,
|
init(timelineProvider: RoomTimelineProvider,
|
||||||
timelineItemFactory: RoomTimelineItemFactory,
|
timelineItemFactory: RoomTimelineItemFactory,
|
||||||
mediaProvider: MediaProviderProtocol) {
|
mediaProvider: MediaProviderProtocol,
|
||||||
|
memberDetailsProvider: MemberDetailsProvider) {
|
||||||
self.timelineProvider = timelineProvider
|
self.timelineProvider = timelineProvider
|
||||||
self.timelineItemFactory = timelineItemFactory
|
self.timelineItemFactory = timelineItemFactory
|
||||||
self.mediaProvider = mediaProvider
|
self.mediaProvider = mediaProvider
|
||||||
|
self.memberDetailsProvider = memberDetailsProvider
|
||||||
|
|
||||||
self.timelineProvider.callbacks.sink { [weak self] callback in
|
self.timelineProvider.callbacks.sink { [weak self] callback in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
@@ -54,33 +57,13 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAvatarIfNeededForTimelineItem(timelineItem)
|
if let item = timelineItem as? EventBasedTimelineItemProtocol {
|
||||||
|
loadAvatarForTimelineItem(item)
|
||||||
switch timelineItem {
|
}
|
||||||
case var item as ImageRoomTimelineItem:
|
|
||||||
if item.image != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let url = item.url else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaProvider.loadImageFromURL(url) { [weak self] result in
|
|
||||||
guard let self = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if case let .success(image) = result {
|
switch timelineItem {
|
||||||
guard let index = self.timelineItems.firstIndex(where: { $0.id == itemId }) else {
|
case let item as ImageRoomTimelineItem:
|
||||||
return
|
loadImageForTimelineItem(item)
|
||||||
}
|
|
||||||
|
|
||||||
item.image = image
|
|
||||||
self.timelineItems[index] = item
|
|
||||||
self.callbacks.send(.updatedTimelineItem(itemId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -126,42 +109,56 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
return Calendar.current.isDate(lhs.originServerTs, inSameDayAs: rhs.originServerTs)
|
return Calendar.current.isDate(lhs.originServerTs, inSameDayAs: rhs.originServerTs)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func loadAvatarIfNeededForTimelineItem(_ timelineItem: RoomTimelineItemProtocol) {
|
private func loadImageForTimelineItem(_ timelineItem: ImageRoomTimelineItem) {
|
||||||
switch timelineItem {
|
var item = timelineItem
|
||||||
case var item as BaseRoomTimelineItemProtocol:
|
|
||||||
if item.shouldShowSenderDetails == false {
|
if item.image != nil {
|
||||||
break
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let url = item.url else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaProvider.loadImageFromURL(url) { [weak self] result in
|
||||||
|
guard let self = self else {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
timelineProvider.avatarURLForUserId(item.sender) { [weak self] result in
|
if case let .success(image) = result {
|
||||||
guard let self = self else {
|
guard let index = self.timelineItems.firstIndex(where: { $0.id == timelineItem.id }) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch result {
|
item.image = image
|
||||||
case .success(let userAvatarURL):
|
self.timelineItems[index] = item
|
||||||
guard let avatarURL = userAvatarURL else {
|
self.callbacks.send(.updatedTimelineItem(timelineItem.id))
|
||||||
return
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
self.mediaProvider.loadImageFromURL(avatarURL) { result in
|
|
||||||
if case let .success(image) = result {
|
private func loadAvatarForTimelineItem(_ timelineItem: EventBasedTimelineItemProtocol) {
|
||||||
guard let index = self.timelineItems.firstIndex(where: { $0.id == timelineItem.id }) else {
|
var item = timelineItem
|
||||||
return
|
|
||||||
}
|
if item.shouldShowSenderDetails == false {
|
||||||
|
return
|
||||||
item.senderAvatar = image
|
}
|
||||||
self.timelineItems[index] = item
|
|
||||||
self.callbacks.send(.updatedTimelineItem(timelineItem.id))
|
memberDetailsProvider.avatarURLForUserId(timelineItem.sender) { result in
|
||||||
|
if case let .success(avatarURL) = result,
|
||||||
|
let avatarURL = avatarURL {
|
||||||
|
self.mediaProvider.loadImageFromURL(avatarURL) { result in
|
||||||
|
if case let .success(image) = result {
|
||||||
|
guard let index = self.timelineItems.firstIndex(where: { $0.id == timelineItem.id }) else {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item.senderAvatar = image
|
||||||
|
self.timelineItems[index] = item
|
||||||
|
self.callbacks.send(.updatedTimelineItem(timelineItem.id))
|
||||||
}
|
}
|
||||||
case .failure:
|
|
||||||
MXLog.error("Failed retrieving user avatar")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// DecorationTimelineItemProtocol.swift
|
||||||
|
// ElementX
|
||||||
|
//
|
||||||
|
// Created by Stefan Ceriu on 18/03/2022.
|
||||||
|
// Copyright © 2022 Element. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
protocol DecorationTimelineItemProtocol: RoomTimelineItemProtocol {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// EventBasedTimelineItemProtocol.swift
|
||||||
|
// ElementX
|
||||||
|
//
|
||||||
|
// Created by Stefan Ceriu on 18/03/2022.
|
||||||
|
// Copyright © 2022 Element. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
protocol EventBasedTimelineItemProtocol: RoomTimelineItemProtocol {
|
||||||
|
var text: String { get }
|
||||||
|
var timestamp: String { get }
|
||||||
|
var shouldShowSenderDetails: Bool { get }
|
||||||
|
|
||||||
|
var sender: String { get }
|
||||||
|
var senderAvatar: UIImage? { get set }
|
||||||
|
}
|
||||||
+1
-1
@@ -9,7 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
struct ImageRoomTimelineItem: BaseRoomTimelineItemProtocol, Identifiable, Equatable {
|
struct ImageRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Equatable {
|
||||||
let id: String
|
let id: String
|
||||||
let text: String
|
let text: String
|
||||||
let timestamp: String
|
let timestamp: String
|
||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct SeparatorRoomTimelineItem: RoomTimelineItemProtocol, Identifiable, Equatable {
|
struct SeparatorRoomTimelineItem: DecorationTimelineItemProtocol, Identifiable, Equatable {
|
||||||
let id: String
|
let id: String
|
||||||
let text: String
|
let text: String
|
||||||
}
|
}
|
||||||
+1
-1
@@ -9,7 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
struct TextRoomTimelineItem: BaseRoomTimelineItemProtocol, Identifiable, Equatable {
|
struct TextRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Equatable {
|
||||||
let id: String
|
let id: String
|
||||||
let text: String
|
let text: String
|
||||||
let timestamp: String
|
let timestamp: String
|
||||||
@@ -11,39 +11,36 @@ import UIKit
|
|||||||
|
|
||||||
struct RoomTimelineItemFactory {
|
struct RoomTimelineItemFactory {
|
||||||
private let mediaProvider: MediaProviderProtocol
|
private let mediaProvider: MediaProviderProtocol
|
||||||
|
private let memberDetailsProvider: MemberDetailsProvider
|
||||||
|
|
||||||
init(mediaProvider: MediaProviderProtocol) {
|
init(mediaProvider: MediaProviderProtocol,
|
||||||
|
memberDetailsProvider: MemberDetailsProvider) {
|
||||||
self.mediaProvider = mediaProvider
|
self.mediaProvider = mediaProvider
|
||||||
|
self.memberDetailsProvider = memberDetailsProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildTimelineItemFor(_ roomMessage: RoomMessageProtocol, showSenderDetails: Bool) -> RoomTimelineItemProtocol {
|
func buildTimelineItemFor(_ roomMessage: RoomMessageProtocol, showSenderDetails: Bool) -> RoomTimelineItemProtocol {
|
||||||
|
|
||||||
|
let avatarURL = memberDetailsProvider.avatarURLForUserId(roomMessage.sender)
|
||||||
|
let avatarImage = mediaProvider.imageForURL(avatarURL)
|
||||||
|
|
||||||
switch roomMessage {
|
switch roomMessage {
|
||||||
case let message as TextRoomMessage:
|
case let message as TextRoomMessage:
|
||||||
return TextRoomTimelineItem(id: message.id,
|
return TextRoomTimelineItem(id: message.id,
|
||||||
text: message.content,
|
text: message.content,
|
||||||
timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened),
|
timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened),
|
||||||
shouldShowSenderDetails: showSenderDetails,
|
shouldShowSenderDetails: showSenderDetails,
|
||||||
sender: message.sender)
|
sender: message.sender,
|
||||||
|
senderAvatar: avatarImage)
|
||||||
case let message as ImageRoomMessage:
|
case let message as ImageRoomMessage:
|
||||||
var image: UIImage?
|
|
||||||
|
|
||||||
if let url = message.url {
|
|
||||||
if mediaProvider.hasImageCachedForURL(url) {
|
|
||||||
mediaProvider.loadImageFromURL(url, { result in
|
|
||||||
if case let .success(cachedImage) = result {
|
|
||||||
image = cachedImage
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ImageRoomTimelineItem(id: message.id,
|
return ImageRoomTimelineItem(id: message.id,
|
||||||
text: message.content,
|
text: message.content,
|
||||||
timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened),
|
timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened),
|
||||||
shouldShowSenderDetails: showSenderDetails,
|
shouldShowSenderDetails: showSenderDetails,
|
||||||
sender: message.sender,
|
sender: message.sender,
|
||||||
|
senderAvatar: avatarImage,
|
||||||
url: message.url,
|
url: message.url,
|
||||||
image: image)
|
image: mediaProvider.imageForURL(message.url))
|
||||||
default:
|
default:
|
||||||
fatalError("Unknown room message.")
|
fatalError("Unknown room message.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,3 @@ import UIKit
|
|||||||
protocol RoomTimelineItemProtocol {
|
protocol RoomTimelineItemProtocol {
|
||||||
var id: String { get }
|
var id: String { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol BaseRoomTimelineItemProtocol: RoomTimelineItemProtocol {
|
|
||||||
var text: String { get }
|
|
||||||
var timestamp: String { get }
|
|
||||||
var shouldShowSenderDetails: Bool { get }
|
|
||||||
|
|
||||||
var sender: String { get }
|
|
||||||
var senderAvatar: UIImage? { get set }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// EventBasedTimelineView.swift
|
||||||
|
// ElementX
|
||||||
|
//
|
||||||
|
// Created by Stefan Ceriu on 18/03/2022.
|
||||||
|
// Copyright © 2022 Element. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct EventBasedTimelineView: View {
|
||||||
|
let timelineItem: EventBasedTimelineItemProtocol
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
if timelineItem.shouldShowSenderDetails {
|
||||||
|
HStack {
|
||||||
|
avatar
|
||||||
|
Text(timelineItem.sender)
|
||||||
|
.font(.footnote)
|
||||||
|
.bold()
|
||||||
|
Spacer()
|
||||||
|
Text(timelineItem.timestamp)
|
||||||
|
.font(.footnote)
|
||||||
|
}
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder private var avatar: some View {
|
||||||
|
ZStack(alignment: .center) {
|
||||||
|
if let avatar = timelineItem.senderAvatar {
|
||||||
|
Image(uiImage: avatar)
|
||||||
|
.resizable()
|
||||||
|
.scaledToFill()
|
||||||
|
.overlay(Circle().stroke(Color(.sRGB, red: 0.05, green: 0.74, blue: 0.55, opacity: 1.0)))
|
||||||
|
} else {
|
||||||
|
PlaceholderAvatarImage(firstCharacter: String(timelineItem.sender.prefix(2).suffix(1)).uppercased())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.clipShape(Circle())
|
||||||
|
.frame(width: 44.0, height: 44.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-5
@@ -14,11 +14,9 @@ struct ImageRoomTimelineView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let image = timelineItem.image {
|
if let image = timelineItem.image {
|
||||||
VStack {
|
VStack(alignment: .leading) {
|
||||||
HStack {
|
EventBasedTimelineView(timelineItem: timelineItem)
|
||||||
Text(timelineItem.text)
|
Text(timelineItem.text)
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
Image(uiImage: image)
|
Image(uiImage: image)
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
+3
-30
@@ -14,40 +14,13 @@ struct TextRoomTimelineView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
if timelineItem.shouldShowSenderDetails {
|
EventBasedTimelineView(timelineItem: timelineItem)
|
||||||
HStack {
|
|
||||||
avatar
|
|
||||||
Text(timelineItem.sender)
|
|
||||||
.font(.footnote)
|
|
||||||
.bold()
|
|
||||||
Spacer()
|
|
||||||
Text(timelineItem.timestamp)
|
|
||||||
.font(.footnote)
|
|
||||||
}
|
|
||||||
Divider()
|
|
||||||
}
|
|
||||||
Text(timelineItem.text)
|
Text(timelineItem.text)
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
}
|
}
|
||||||
.id(timelineItem.id)
|
.id(timelineItem.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder var avatar: some View {
|
|
||||||
ZStack(alignment: .center) {
|
|
||||||
Circle()
|
|
||||||
.fill(Color(.sRGB, red: 0.05, green: 0.74, blue: 0.55, opacity: 1.0))
|
|
||||||
if let avatar = timelineItem.senderAvatar {
|
|
||||||
Image(uiImage: avatar)
|
|
||||||
.resizable()
|
|
||||||
.clipShape(Circle())
|
|
||||||
} else {
|
|
||||||
Text(timelineItem.sender.prefix(2).suffix(1))
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.font(.title)
|
|
||||||
.bold()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.frame(width: 44.0, height: 44.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TextRoomTimelineView_Previews: PreviewProvider {
|
struct TextRoomTimelineView_Previews: PreviewProvider {
|
||||||
Reference in New Issue
Block a user