App polish part 3 (#1135)

- Add an animation to long press on messages.
- Make emojis bigger on the reactions picker screen.
- Remove quote menu action.
- Fix emoji picker handle overlapping focused search field.
- Update launch, splash and onboarding screens.
- Use elevation tokens in Forms.
- Move the cancel button on the Start Chat flow.
This commit is contained in:
Doug 2023-06-22 14:37:47 +01:00 committed by GitHub
parent e65a2d2431
commit f2312f6f70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 2054 additions and 5570 deletions

View File

@ -12,7 +12,7 @@ let package = Package(
.library(name: "DesignKit", targets: ["DesignKit"])
],
dependencies: [
.package(url: "https://github.com/vector-im/compound-ios.git", revision: "e8b35fdd8c4008079dfce203e63bf7a05582d7b9"),
.package(url: "https://github.com/vector-im/compound-ios.git", revision: "d1a28b8a311e33ddb517d10391037f1547a3c7b6"),
.package(url: "https://github.com/vector-im/element-design-tokens.git", exact: "0.0.3"),
.package(url: "https://github.com/siteline/SwiftUI-Introspect.git", from: "0.1.4")
],

View File

@ -61,23 +61,10 @@ public struct ElementColors {
// MARK: - Temp
/// The colour to use on the background of a Form or grouped List.
///
/// This colour is a special case as it uses `system` in light mode and `background` in dark mode.
public var formBackground: Color {
Color(UIColor { collection in
collection.userInterfaceStyle == .light ? UIColor(.compound.bgSubtleSecondary) : UIColor(.compound.bgCanvasDefault)
})
}
/// The background colour of a row in a Form or grouped List.
///
/// This colour is a special case as it uses `background` in light mode and `system` in dark mode.
public var formRowBackground: Color {
Color(UIColor { collection in
collection.userInterfaceStyle == .light ? UIColor(.compound.bgCanvasDefault) : UIColor(.compound.bgSubtleSecondary)
})
}
/// This colour will be removed once Compound form styles are used everywhere.
public var formRowBackground = Color.compound.bgCanvasDefaultLevel1
}
private extension String {

View File

@ -126,6 +126,7 @@
30CC1DB7CE357659C82AA115 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; };
30CC4F796B27BE8B1DFDBF5A /* NSEUserSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEAA2832D93EC7D2608703FB /* NSEUserSession.swift */; };
3113065AABBC14CEAE6843FA /* UserSessionFlowCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8774CF614849664B5B3C2A1 /* UserSessionFlowCoordinatorStateMachine.swift */; };
329571083B132E4941131835 /* OnboardingBackgroundImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 686BCFA37AC6C67FF973CE67 /* OnboardingBackgroundImage.swift */; };
339BC18777912E1989F2F17D /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584A61D9C459FAFEF038A7C0 /* Section.swift */; };
339D847497C51F2B36E3666B /* FixedIconSizeLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3518637393394901BF5BFAC3 /* FixedIconSizeLabelStyle.swift */; };
33CAC1226DFB8B5D8447D286 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
@ -167,6 +168,7 @@
42A5A42ACF063EEE6B1980D2 /* ReportContentScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81B17B1F29448D1B9049B11C /* ReportContentScreenViewModel.swift */; };
42B084FDE621FBEE433AF444 /* LegalInformationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4176C3E20C772DE8D182863C /* LegalInformationScreen.swift */; };
42F1C8731166633E35A6D7E6 /* RoomEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A307A44F952CD73E63AE31 /* RoomEventStringBuilder.swift */; };
4362C770C7E05ADC750E5070 /* LongPressWithFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21DC6A9917A7123E7E9A3F81 /* LongPressWithFeedback.swift */; };
43EF6D8E694F54C5471BF5F3 /* TimelineBubbleLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DCA495ED42D2463DDAA94D /* TimelineBubbleLayout.swift */; };
43F35A7E5703D64DB0519C59 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */; };
440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */; };
@ -178,7 +180,6 @@
46BA7F4B4D3A7164DED44B88 /* FullscreenDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 565F1B2B300597C616B37888 /* FullscreenDialog.swift */; };
47305C0911C9E1AA774A4000 /* TemplateScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA90BD288E5AE6BC643AFDDF /* TemplateScreenCoordinator.swift */; };
4799A852132F1744E2825994 /* CreateRoomViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340179A0FC1AD4AEDA7FC134 /* CreateRoomViewModelProtocol.swift */; };
48FE5F0E3921146DBF4E61E7 /* OnboardingBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06A27D9C70E0DCC1E199163 /* OnboardingBackgroundView.swift */; };
492274DA6691EE985C2FCCAA /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; };
496CC9D59ACFAB84FD9B3B5F /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840E86A67DB2C92C09771EAD /* AnalyticsPromptScreenModels.swift */; };
49814A48470F347426513B07 /* TimelineReadReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1877038D1AD3D5A029F8AE2C /* TimelineReadReceiptsView.swift */; };
@ -569,7 +570,6 @@
CF82143AA4A4F7BD11D22946 /* RoomTimelineViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACB6C5E4950B6C9842F35A38 /* RoomTimelineViewProvider.swift */; };
D02AA6208C7ACB9BE6332394 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
D181AC8FF236B7F91C0A8C28 /* MapTiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23AA3F4B285570805CB0CCDD /* MapTiler.swift */; };
D25D26ACF2F1263092678C84 /* FormSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1DFE6E746539F33042D3A9 /* FormSection.swift */; };
D2A15D03F81342A09340BD56 /* AnalyticsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFEEE93B82937B2E86F92EB /* AnalyticsScreen.swift */; };
D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; };
D33AC79A50DFC26D2498DD28 /* FileRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */; };
@ -829,6 +829,7 @@
2141693488CE5446BB391964 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItemContent.swift; sourceTree = "<group>"; };
218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedTimelineItemProtocol.swift; sourceTree = "<group>"; };
21DC6A9917A7123E7E9A3F81 /* LongPressWithFeedback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongPressWithFeedback.swift; sourceTree = "<group>"; };
225EFCA26877E75CDFE7F48D /* MapTilerStyleBuilderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilderProtocol.swift; sourceTree = "<group>"; };
22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenViewModelProtocol.swift; sourceTree = "<group>"; };
227AC5D71A4CE43512062243 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
@ -936,7 +937,6 @@
4E47F18A9A077E351CEA10D4 /* TextBasedRoomTimelineViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewProtocol.swift; sourceTree = "<group>"; };
4E625B0EB2F86B37C14EF7E6 /* SettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenViewModel.swift; sourceTree = "<group>"; };
4F0CB536D1C3CC15AA740CC6 /* AuthenticationServiceProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxyProtocol.swift; sourceTree = "<group>"; };
4F1DFE6E746539F33042D3A9 /* FormSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormSection.swift; sourceTree = "<group>"; };
4FCB2126C091EEF2454B4D56 /* RoomFlowCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomFlowCoordinatorTests.swift; sourceTree = "<group>"; };
4FD6E621CC5E6D4830D96D2D /* MockMediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaProvider.swift; sourceTree = "<group>"; };
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
@ -993,6 +993,7 @@
669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessor.swift; sourceTree = "<group>"; };
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
6861FE915C7B5466E6962BBA /* StartChatScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreen.swift; sourceTree = "<group>"; };
686BCFA37AC6C67FF973CE67 /* OnboardingBackgroundImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBackgroundImage.swift; sourceTree = "<group>"; };
69219A908D7C22E6EE6689AE /* UserNotificationCenterSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterSpy.swift; sourceTree = "<group>"; };
693E16574C6F7F9FA1015A8C /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = "<group>"; };
69B63F817FE305548DB4B512 /* RoomMembersListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListViewModelTests.swift; sourceTree = "<group>"; };
@ -1255,7 +1256,6 @@
CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = "<group>"; };
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = "<group>"; };
CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxy.swift; sourceTree = "<group>"; };
D06A27D9C70E0DCC1E199163 /* OnboardingBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBackgroundView.swift; sourceTree = "<group>"; };
D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = "<group>"; };
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
@ -1579,7 +1579,6 @@
95A1CCDEE545CB6453B084BF /* FormButtonStyles.swift */,
E80F9E9B93B6ECE9A937B1C6 /* FormRow.swift */,
D1897720266C036471AD9D1B /* FormRowLabelStyle.swift */,
4F1DFE6E746539F33042D3A9 /* FormSection.swift */,
);
path = "Form Styles";
sourceTree = "<group>";
@ -2470,7 +2469,7 @@
7B14834450AE76EEFDDBCBB8 /* View */ = {
isa = PBXGroup;
children = (
D06A27D9C70E0DCC1E199163 /* OnboardingBackgroundView.swift */,
686BCFA37AC6C67FF973CE67 /* OnboardingBackgroundImage.swift */,
AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */,
);
path = View;
@ -2755,6 +2754,7 @@
A312471EA62EFB0FD94E60DC /* Style */ = {
isa = PBXGroup;
children = (
21DC6A9917A7123E7E9A3F81 /* LongPressWithFeedback.swift */,
E2DCA495ED42D2463DDAA94D /* TimelineBubbleLayout.swift */,
98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */,
94BCC8A9C73C1F838122C645 /* TimelineItemPlainStylerView.swift */,
@ -4023,7 +4023,6 @@
B3EDDEC1839BB5A3747624BB /* FormButtonStyles.swift in Sources */,
5CE74302A0725F56F1E9D2A0 /* FormRow.swift in Sources */,
4166A7DD2A4E2EFF0EB9369B /* FormRowLabelStyle.swift in Sources */,
D25D26ACF2F1263092678C84 /* FormSection.swift in Sources */,
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */,
85AFBB433AD56704A880F8A0 /* FramePreferenceKey.swift in Sources */,
46BA7F4B4D3A7164DED44B88 /* FullscreenDialog.swift in Sources */,
@ -4077,6 +4076,7 @@
C5A07E2D88BE7D51DCECD166 /* LoginScreenModels.swift in Sources */,
BDA68E8D95B2B24B28825B8B /* LoginScreenViewModel.swift in Sources */,
A5B9EF45C7B8ACEB4954AE36 /* LoginScreenViewModelProtocol.swift in Sources */,
4362C770C7E05ADC750E5070 /* LongPressWithFeedback.swift in Sources */,
B94368839BDB69172E28E245 /* MXLog.swift in Sources */,
B66757D0254843162595B25D /* MXLogger.swift in Sources */,
C1D0AB8222D7BAFC9AF9C8C0 /* MapLibreMapView.swift in Sources */,
@ -4136,7 +4136,7 @@
652ACCF104A8CEF30788963C /* NotificationManager.swift in Sources */,
06D3942496E9E0E655F14D21 /* NotificationManagerProtocol.swift in Sources */,
9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */,
48FE5F0E3921146DBF4E61E7 /* OnboardingBackgroundView.swift in Sources */,
329571083B132E4941131835 /* OnboardingBackgroundImage.swift in Sources */,
2CB6787E25B11711518E9588 /* OnboardingCoordinator.swift in Sources */,
5D7960B32C350FA93F48D02B /* OnboardingModels.swift in Sources */,
7F64FA937B95924B3A44EC12 /* OnboardingScreen.swift in Sources */,
@ -5020,7 +5020,7 @@
repositoryURL = "https://github.com/vector-im/compound-ios";
requirement = {
kind = revision;
revision = e8b35fdd8c4008079dfce203e63bf7a05582d7b9;
revision = d1a28b8a311e33ddb517d10391037f1547a3c7b6;
};
};
9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {

View File

@ -13,7 +13,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/vector-im/compound-ios",
"state" : {
"revision" : "e8b35fdd8c4008079dfce203e63bf7a05582d7b9"
"revision" : "d1a28b8a311e33ddb517d10391037f1547a3c7b6"
}
},
{

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"filename" : "OnboardingBackgroundPart1.pdf",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "OnboardingBackgroundPart1-Dark.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"filename" : "OnboardingBackgroundPart2.pdf",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "OnboardingBackgroundPart2-Dark.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"filename" : "OnboardingBackgroundPart3.pdf",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "OnboardingBackgroundPart3-Dark.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "LaunchBackgroundTablet-squashed.png",
"idiom" : "universal"
},
{
"filename" : "LaunchBackgroundPhone-squashed.png",
"idiom" : "iphone"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 921 KiB

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "OnboardingSplashAppLogo.pdf",
"filename" : "LaunchLogo.pdf",
"idiom" : "universal"
},
{
@ -11,7 +11,7 @@
"value" : "dark"
}
],
"filename" : "OnboardingSplashAppLogo-Dark.pdf",
"filename" : "LaunchLogo-dark.pdf",
"idiom" : "universal"
}
],

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,397 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << /ExtGState << /E1 << /ca 0.400000 >> >> >>
/BBox [ 0.000000 0.000000 158.000000 158.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
1.000000 1.000000 1.000000 scn
0.000000 87.599998 m
0.000000 112.242310 0.000000 124.563461 4.795713 133.975586 c
9.014142 142.254715 15.745286 148.985855 24.024418 153.204285 c
33.436535 158.000000 45.757690 158.000000 70.400002 158.000000 c
87.599998 158.000000 l
112.242310 158.000000 124.563469 158.000000 133.975586 153.204285 c
142.254715 148.985855 148.985855 142.254715 153.204285 133.975586 c
158.000000 124.563461 158.000000 112.242310 158.000000 87.599998 c
158.000000 70.400002 l
158.000000 45.757690 158.000000 33.436531 153.204285 24.024414 c
148.985855 15.745285 142.254715 9.014145 133.975586 4.795715 c
124.563469 0.000000 112.242310 0.000000 87.599998 0.000000 c
70.400002 0.000000 l
45.757690 0.000000 33.436535 0.000000 24.024418 4.795715 c
15.745286 9.014145 9.014142 15.745285 4.795713 24.024414 c
0.000000 33.436531 0.000000 45.757690 0.000000 70.400002 c
0.000000 87.599998 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 24.000000 24.000000 cm
0.050980 0.741176 0.545098 scn
55.000008 -0.000015 m
85.375671 -0.000015 110.000015 24.624329 110.000015 54.999992 c
110.000015 85.375656 85.375671 110.000000 55.000008 110.000000 c
24.624342 110.000000 0.000000 85.375656 0.000000 54.999992 c
0.000000 24.624329 24.624342 -0.000015 55.000008 -0.000015 c
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 45.606445 81.127930 cm
1.000000 1.000000 1.000000 scn
23.337296 27.245094 m
23.337296 29.465168 25.140764 31.264893 27.365456 31.264893 c
42.443832 31.264893 54.667271 19.066826 54.667271 4.019749 c
54.667271 1.799677 52.863808 -0.000048 50.639114 -0.000048 c
48.414425 -0.000048 46.610954 1.799677 46.610954 4.019749 c
46.610954 14.626682 37.994453 23.225300 27.365456 23.225298 c
25.140764 23.225298 23.337296 25.025023 23.337296 27.245094 c
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 45.606445 81.127930 cm
1.000000 1.000000 1.000000 scn
62.757961 8.039566 m
64.982651 8.039566 66.786118 6.239841 66.786118 4.019770 c
66.786118 -11.027309 54.562679 -23.225376 39.484303 -23.225376 c
37.259613 -23.225376 35.456146 -21.425652 35.456146 -19.205582 c
35.456146 -16.985508 37.259613 -15.185780 39.484303 -15.185780 c
50.113300 -15.185780 58.729801 -6.587162 58.729801 4.019770 c
58.729801 6.239841 60.533272 8.039566 62.757961 8.039566 c
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 45.606445 81.127930 cm
1.000000 1.000000 1.000000 scn
43.512127 -31.500816 m
43.512127 -33.720894 41.708656 -35.520615 39.483967 -35.520615 c
24.405590 -35.520615 12.182150 -23.322544 12.182151 -8.275467 c
12.182151 -6.055397 13.985620 -4.255672 16.210310 -4.255672 c
18.435001 -4.255672 20.238468 -6.055397 20.238468 -8.275471 c
20.238468 -18.882404 28.854971 -27.481022 39.483967 -27.481022 c
41.708656 -27.481022 43.512127 -29.280746 43.512127 -31.500816 c
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 45.606445 81.127686 cm
1.000000 1.000000 1.000000 scn
4.028159 -12.295063 m
1.803469 -12.295063 0.000000 -10.495338 0.000000 -8.275265 c
-0.000001 6.771814 12.223439 18.969881 27.301817 18.969883 c
29.526506 18.969883 31.329973 17.170158 31.329975 14.950085 c
31.329975 12.730011 29.526506 10.930288 27.301817 10.930288 c
16.672821 10.930286 8.056316 2.331669 8.056317 -8.275265 c
8.056318 -10.495338 6.252850 -12.295063 4.028159 -12.295063 c
h
f*
n
Q
endstream
endobj
2 0 obj
3367
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 158.000000 158.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 87.599998 m
0.000000 112.242310 0.000000 124.563461 4.795713 133.975586 c
9.014142 142.254715 15.745286 148.985855 24.024418 153.204285 c
33.436535 158.000000 45.757690 158.000000 70.400002 158.000000 c
87.599998 158.000000 l
112.242310 158.000000 124.563469 158.000000 133.975586 153.204285 c
142.254715 148.985855 148.985855 142.254715 153.204285 133.975586 c
158.000000 124.563461 158.000000 112.242310 158.000000 87.599998 c
158.000000 70.400002 l
158.000000 45.757690 158.000000 33.436531 153.204285 24.024414 c
148.985855 15.745285 142.254715 9.014145 133.975586 4.795715 c
124.563469 0.000000 112.242310 0.000000 87.599998 0.000000 c
70.400002 0.000000 l
45.757690 0.000000 33.436535 0.000000 24.024418 4.795715 c
15.745286 9.014145 9.014142 15.745285 4.795713 24.024414 c
0.000000 33.436531 0.000000 45.757690 0.000000 70.400002 c
0.000000 87.599998 l
h
f
n
Q
endstream
endobj
4 0 obj
996
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
q
0.000000 87.599998 m
0.000000 112.242310 0.000000 124.563461 4.795713 133.975586 c
9.014142 142.254715 15.745286 148.985855 24.024418 153.204285 c
33.436535 158.000000 45.757690 158.000000 70.400002 158.000000 c
87.599998 158.000000 l
112.242310 158.000000 124.563469 158.000000 133.975586 153.204285 c
142.254715 148.985855 148.985855 142.254715 153.204285 133.975586 c
158.000000 124.563461 158.000000 112.242310 158.000000 87.599998 c
158.000000 70.400002 l
158.000000 45.757690 158.000000 33.436531 153.204285 24.024414 c
148.985855 15.745285 142.254715 9.014145 133.975586 4.795715 c
124.563469 0.000000 112.242310 0.000000 87.599998 0.000000 c
70.400002 0.000000 l
45.757690 0.000000 33.436535 0.000000 24.024418 4.795715 c
15.745286 9.014145 9.014142 15.745285 4.795713 24.024414 c
0.000000 33.436531 0.000000 45.757690 0.000000 70.400002 c
0.000000 87.599998 l
h
W*
n
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
1.000000 1.000000 1.000000 scn
24.024418 4.795715 m
24.251413 5.241211 l
24.024418 4.795715 l
h
4.795713 24.024414 m
4.350210 23.797424 l
4.795713 24.024414 l
h
153.204285 24.024414 m
152.758789 24.251419 l
153.204285 24.024414 l
h
133.975586 4.795715 m
133.748581 5.241211 l
133.975586 4.795715 l
h
153.204285 133.975586 m
152.758789 133.748581 l
153.204285 133.975586 l
h
24.024418 153.204285 m
23.797422 153.649796 l
24.024418 153.204285 l
h
70.400002 157.500000 m
87.599998 157.500000 l
87.599998 158.500000 l
70.400002 158.500000 l
70.400002 157.500000 l
h
157.500000 87.599998 m
157.500000 70.400002 l
158.500000 70.400002 l
158.500000 87.599998 l
157.500000 87.599998 l
h
87.599998 0.500000 m
70.400002 0.500000 l
70.400002 -0.500000 l
87.599998 -0.500000 l
87.599998 0.500000 l
h
0.500000 70.400002 m
0.500000 87.599998 l
-0.500000 87.599998 l
-0.500000 70.400002 l
0.500000 70.400002 l
h
70.400002 0.500000 m
58.070595 0.500000 48.853611 0.500381 41.541603 1.097809 c
34.235432 1.694748 28.875237 2.885254 24.251413 5.241211 c
23.797422 4.350204 l
28.585714 1.910446 34.092159 0.703110 41.460171 0.101120 c
48.822346 -0.500381 58.087097 -0.500000 70.400002 -0.500000 c
70.400002 0.500000 l
h
-0.500000 70.400002 m
-0.500000 58.087097 -0.500389 48.822350 0.101125 41.460167 c
0.703115 34.092155 1.910453 28.585709 4.350210 23.797424 c
5.241217 24.251419 l
2.885260 28.875244 1.694741 34.235428 1.097804 41.541603 c
0.500389 48.853615 0.500000 58.070595 0.500000 70.400002 c
-0.500000 70.400002 l
h
24.251413 5.241211 m
16.066362 9.411713 9.411708 16.066360 5.241217 24.251419 c
4.350210 23.797424 l
8.616575 15.424210 15.424210 8.616577 23.797422 4.350204 c
24.251413 5.241211 l
h
157.500000 70.400002 m
157.500000 58.070595 157.499619 48.853615 156.902191 41.541603 c
156.305252 34.235428 155.114746 28.875244 152.758789 24.251419 c
153.649796 23.797424 l
156.089554 28.585709 157.296890 34.092155 157.898880 41.460167 c
158.500381 48.822350 158.500000 58.087097 158.500000 70.400002 c
157.500000 70.400002 l
h
87.599998 -0.500000 m
99.912903 -0.500000 109.177650 -0.500381 116.539833 0.101120 c
123.907845 0.703110 129.414291 1.910446 134.202576 4.350204 c
133.748581 5.241211 l
129.124756 2.885254 123.764572 1.694748 116.458397 1.097809 c
109.146385 0.500381 99.929405 0.500000 87.599998 0.500000 c
87.599998 -0.500000 l
h
152.758789 24.251419 m
148.588287 16.066360 141.933640 9.411713 133.748581 5.241211 c
134.202576 4.350204 l
142.575790 8.616577 149.383423 15.424210 153.649796 23.797424 c
152.758789 24.251419 l
h
87.599998 157.500000 m
99.929405 157.500000 109.146385 157.499619 116.458397 156.902191 c
123.764572 156.305252 129.124756 155.114746 133.748581 152.758789 c
134.202576 153.649796 l
129.414291 156.089554 123.907845 157.296890 116.539833 157.898880 c
109.177650 158.500381 99.912903 158.500000 87.599998 158.500000 c
87.599998 157.500000 l
h
158.500000 87.599998 m
158.500000 99.912903 158.500381 109.177658 157.898880 116.539825 c
157.296890 123.907837 156.089554 129.414291 153.649796 134.202576 c
152.758789 133.748581 l
155.114746 129.124756 156.305252 123.764572 156.902191 116.458397 c
157.499619 109.146393 157.500000 99.929405 157.500000 87.599998 c
158.500000 87.599998 l
h
133.748581 152.758789 m
141.933640 148.588287 148.588287 141.933640 152.758789 133.748581 c
153.649796 134.202576 l
149.383423 142.575790 142.575790 149.383423 134.202576 153.649796 c
133.748581 152.758789 l
h
70.400002 158.500000 m
58.087097 158.500000 48.822346 158.500381 41.460171 157.898880 c
34.092159 157.296890 28.585714 156.089554 23.797422 153.649796 c
24.251413 152.758789 l
28.875237 155.114746 34.235432 156.305252 41.541603 156.902191 c
48.853611 157.499619 58.070595 157.500000 70.400002 157.500000 c
70.400002 158.500000 l
h
0.500000 87.599998 m
0.500000 99.929405 0.500389 109.146393 1.097804 116.458397 c
1.694741 123.764572 2.885260 129.124756 5.241217 133.748581 c
4.350210 134.202576 l
1.910453 129.414291 0.703115 123.907837 0.101125 116.539825 c
-0.500389 109.177658 -0.500000 99.912903 -0.500000 87.599998 c
0.500000 87.599998 l
h
23.797422 153.649796 m
15.424210 149.383423 8.616575 142.575790 4.350210 134.202576 c
5.241217 133.748581 l
9.411708 141.933640 16.066362 148.588287 24.251413 152.758789 c
23.797422 153.649796 l
h
f
n
Q
Q
endstream
endobj
7 0 obj
5258
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 158.000000 158.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000003667 00000 n
0000003690 00000 n
0000004936 00000 n
0000004958 00000 n
0000005256 00000 n
0000010570 00000 n
0000010593 00000 n
0000010768 00000 n
0000010842 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
10902
%%EOF

View File

@ -254,8 +254,9 @@
"screen_onboarding_sign_in_with_qr_code" = "Sign in with QR code";
"screen_onboarding_sign_up" = "Create account";
"screen_onboarding_subtitle" = "Communicate and collaborate securely";
"screen_onboarding_welcome_message" = "Welcome to the fastest Element ever. Supercharged for speed and simplicity.";
"screen_onboarding_welcome_subtitle" = "Welcome to %1$@. Supercharged, for speed and simplicity.";
"screen_onboarding_welcome_title" = "Be in your Element";
"screen_onboarding_welcome_title" = "Be in your element";
"screen_report_content_block_user_hint" = "Check if you want to hide all current and future messages from this user";
"screen_room_attachment_source_camera" = "Camera";
"screen_room_attachment_source_camera_photo" = "Take photo";

View File

@ -491,8 +491,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
}
private func presentEmojiPicker(for itemId: String) {
let emojiPickerNavigationStackCoordinator = NavigationStackCoordinator()
let params = EmojiPickerScreenCoordinatorParameters(emojiProvider: emojiProvider,
itemId: itemId)
let coordinator = EmojiPickerScreenCoordinator(parameters: params)
@ -509,10 +507,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
}
}
emojiPickerNavigationStackCoordinator.setRootCoordinator(coordinator)
emojiPickerNavigationStackCoordinator.presentationDetents = [.medium, .large]
navigationStackCoordinator.setSheetCoordinator(emojiPickerNavigationStackCoordinator) { [weak self] in
navigationStackCoordinator.setSheetCoordinator(coordinator) { [weak self] in
self?.stateMachine.tryEvent(.dismissEmojiPicker)
}
}

View File

@ -30,18 +30,18 @@ internal enum Asset {
internal enum Images {
internal static let analyticsCheckmark = ImageAsset(name: "Images/AnalyticsCheckmark")
internal static let analyticsLogo = ImageAsset(name: "Images/AnalyticsLogo")
internal static let onboardingAppLogo = ImageAsset(name: "Images/Onboarding App Logo")
internal static let onboardingBackgroundPart1 = ImageAsset(name: "Images/Onboarding Background Part 1")
internal static let onboardingBackgroundPart2 = ImageAsset(name: "Images/Onboarding Background Part 2")
internal static let onboardingBackgroundPart3 = ImageAsset(name: "Images/Onboarding Background Part 3")
internal static let serverSelectionIcon = ImageAsset(name: "Images/Server Selection Icon")
internal static let encryptionNormal = ImageAsset(name: "Images/encryption_normal")
internal static let encryptionTrusted = ImageAsset(name: "Images/encryption_trusted")
internal static let encryptionWarning = ImageAsset(name: "Images/encryption_warning")
internal static let launchBackground = ImageAsset(name: "Images/LaunchBackground")
internal static let launchLogo = ImageAsset(name: "Images/LaunchLogo")
internal static let appLogo = ImageAsset(name: "Images/app-logo")
internal static let closeCircle = ImageAsset(name: "Images/close_circle")
internal static let timelineComposerSendMessage = ImageAsset(name: "Images/timelineComposerSendMessage")
}
internal static let launchLogo = ImageAsset(name: "LaunchLogo")
internal static let onboardingBackground = ImageAsset(name: "OnboardingBackground")
}
// swiftlint:enable identifier_name line_length nesting type_body_length type_name

View File

@ -644,11 +644,13 @@ public enum L10n {
public static var screenOnboardingSignUp: String { return L10n.tr("Localizable", "screen_onboarding_sign_up") }
/// Communicate and collaborate securely
public static var screenOnboardingSubtitle: String { return L10n.tr("Localizable", "screen_onboarding_subtitle") }
/// Welcome to the fastest Element ever. Supercharged for speed and simplicity.
public static var screenOnboardingWelcomeMessage: String { return L10n.tr("Localizable", "screen_onboarding_welcome_message") }
/// Welcome to %1$@. Supercharged, for speed and simplicity.
public static func screenOnboardingWelcomeSubtitle(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_onboarding_welcome_subtitle", String(describing: p1))
}
/// Be in your Element
/// Be in your element
public static var screenOnboardingWelcomeTitle: String { return L10n.tr("Localizable", "screen_onboarding_welcome_title") }
/// Block user
public static var screenReportContentBlockUser: String { return L10n.tr("Localizable", "screen_report_content_block_user") }

View File

@ -49,8 +49,8 @@ struct FormRowAccessory: View {
switch kind {
case .navigationLink:
Image(systemName: "chevron.forward")
.font(.compound.bodyMD.bold())
.foregroundColor(.compound.iconQuaternary)
.font(.compound.bodyMDSemibold)
.foregroundColor(.compound.iconTertiaryAlpha)
case .progressView:
ProgressView()
case .singleSelection(let isSelected):
@ -111,9 +111,9 @@ struct FormButtonStyle: PrimitiveButtonStyle {
private func backgroundColor(for configuration: Configuration) -> Color {
switch accessory?.kind {
case .none, .navigationLink, .progressView:
return configuration.isPressed ? .compound.bgSubtlePrimary : .element.formRowBackground
return configuration.isPressed ? .compound.bgSubtlePrimary : .compound.bgCanvasDefaultLevel1
default:
return .element.formRowBackground
return .compound.bgCanvasDefaultLevel1
}
}
}
@ -133,7 +133,7 @@ struct FormActionButtonStyle: ButtonStyle {
.frame(width: menuIconSize, height: menuIconSize)
.background {
RoundedRectangle(cornerRadius: 16)
.fill(configuration.isPressed ? Color.compound.bgSubtlePrimary : .element.formRowBackground)
.fill(configuration.isPressed ? Color.compound.bgSubtlePrimary : .compound.bgCanvasDefaultLevel1)
}
Text(title)
@ -165,7 +165,7 @@ struct FormButtonStyles_Previews: PreviewProvider {
ShareLink(item: "test")
.buttonStyle(FormButtonStyle())
}
.formSectionStyle()
.compoundFormSection()
Section("Single selection") {
Button { } label: {
@ -189,7 +189,7 @@ struct FormButtonStyles_Previews: PreviewProvider {
}
.buttonStyle(FormButtonStyle(accessory: .singleSelection(isSelected: false)))
}
.formSectionStyle()
.compoundFormSection()
Section("Multiple selection") {
Button { } label: {
@ -213,7 +213,7 @@ struct FormButtonStyles_Previews: PreviewProvider {
}
.buttonStyle(FormButtonStyle(accessory: .multipleSelection(isSelected: false)))
}
.formSectionStyle()
.compoundFormSection()
Section {
Button(role: .destructive) { } label: {
@ -221,7 +221,7 @@ struct FormButtonStyles_Previews: PreviewProvider {
}
.buttonStyle(FormButtonStyle())
}
.formSectionStyle()
.compoundFormSection()
}
}
}

View File

@ -32,9 +32,9 @@ struct FormRowLabelStyle: LabelStyle {
private var iconBackgroundColor: Color {
if role == .destructive {
return .compound.textCriticalPrimary.opacity(0.1)
return .compound._bgCriticalSubtleAlpha
} else {
return .element.formBackground
return .compound._bgSubtleSecondaryAlpha
}
}
@ -42,7 +42,7 @@ struct FormRowLabelStyle: LabelStyle {
if role == .destructive {
return .compound.textCriticalPrimary
} else {
return .compound.iconSecondary
return .compound.iconTertiaryAlpha
}
}

View File

@ -1,38 +0,0 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import SwiftUI
extension View {
/// Applies a standard style to forms.
func elementFormStyle() -> some View {
scrollContentBackground(.hidden)
.background(Color.element.formBackground.ignoresSafeArea())
}
/// Applies a standard style for form header text.
func formSectionHeader() -> some View {
foregroundColor(.compound.textSecondary)
.font(.compound.bodyXS)
}
/// Applies a standard style for form sections.
func formSectionStyle() -> some View {
listRowSeparator(.hidden)
.listRowInsets(FormRow.insets)
.listRowBackground(Color.element.formRowBackground)
}
}

View File

@ -31,7 +31,7 @@ struct CreateRoomScreen: View {
topicSection
securitySection
}
.elementFormStyle()
.compoundForm()
.track(screen: .createRoom)
.scrollDismissesKeyboard(.immediately)
.navigationTitle(L10n.screenCreateRoomTitle)
@ -83,9 +83,8 @@ struct CreateRoomScreen: View {
}
VStack(alignment: .leading, spacing: 8) {
Text(L10n.screenCreateRoomRoomNameLabel.uppercased())
.font(.compound.bodyXS)
.padding(.leading, 16)
.formSectionHeader()
.padding(.leading, FormRow.insets.leading)
.compoundFormSectionHeader()
TextField(L10n.screenCreateRoomRoomNameLabel,
text: $context.roomName,
prompt: Text(L10n.commonRoomNamePlaceholder).foregroundColor(.compound.textPlaceholder),
@ -100,7 +99,7 @@ struct CreateRoomScreen: View {
.listRowInsets(.init())
.listRowBackground(Color.clear)
}
.formSectionStyle()
.compoundFormSection()
}
private var cameraImage: some View {
@ -123,13 +122,13 @@ struct CreateRoomScreen: View {
.lineLimit(3, reservesSpace: false)
} header: {
Text(L10n.screenCreateRoomTopicLabel)
.formSectionHeader()
.compoundFormSectionHeader()
} footer: {
if !context.viewState.selectedUsers.isEmpty {
selectedUsersSection
}
}
.formSectionStyle()
.compoundFormSection()
}
@State private var frame: CGRect = .zero
@ -185,7 +184,7 @@ struct CreateRoomScreen: View {
.pickerStyle(.inline)
} header: {
Text(L10n.commonSecurity.uppercased())
.formSectionHeader()
.compoundFormSectionHeader()
.padding(.top, 40)
}
.listRowSeparatorTint(.compound.borderDisabled)

View File

@ -19,24 +19,30 @@ import SwiftUI
struct EmojiPickerScreen: View {
@ObservedObject var context: EmojiPickerScreenViewModel.Context
@State var searchString = ""
@ScaledMetric(relativeTo: .title) var minimumWidth: Double = 50
@State private var isSearching = false
@ScaledMetric(relativeTo: .title) var minimumWidth: Double = 64
var body: some View {
NavigationStack {
ScrollView {
LazyVGrid(columns: [GridItem(.adaptive(minimum: minimumWidth))], spacing: 16) {
ForEach(context.viewState.categories) { category in
Section(header: EmojiPickerScreenHeaderView(title: category.name)
.padding(.horizontal, 13)
.padding(.top, 10)) {
Section {
ForEach(category.emojis) { emoji in
Button {
context.send(viewAction: .emojiTapped(emoji: emoji))
} label: {
Text(emoji.value)
.font(.compound.headingLG)
.font(.compound.headingXL)
}
}
} header: {
EmojiPickerScreenHeaderView(title: category.name)
.padding(.horizontal, 13)
.padding(.top, 10)
}
}
}
@ -45,8 +51,12 @@ struct EmojiPickerScreen: View {
.navigationTitle(L10n.commonReactions)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
.modifier(IsSearching(isSearching: $isSearching))
.searchable(text: $searchString, placement: .navigationBarDrawer(displayMode: .always))
.compoundSearchField()
}
.presentationDetents([.medium, .large])
.presentationDragIndicator(isSearching ? .hidden : .visible)
.onChange(of: searchString) { _ in
context.send(viewAction: .search(searchString: searchString))
}
@ -62,12 +72,30 @@ struct EmojiPickerScreen: View {
}
}
/// A view modifier to extract whether the search field is focussed from a subview.
private struct IsSearching: ViewModifier {
@Environment(\.isSearching) private var isSearchFieldFocused
@Binding var isSearching: Bool
func body(content: Content) -> some View {
content
.onChange(of: isSearchFieldFocused) { isSearching = $0 }
}
}
// MARK: - Previews
struct EmojiPickerScreen_Previews: PreviewProvider {
static let viewModel = EmojiPickerScreenViewModel(emojiProvider: EmojiProvider())
static var previews: some View {
NavigationStack {
EmojiPickerScreen(context: EmojiPickerScreenViewModel(emojiProvider: EmojiProvider()).context)
EmojiPickerScreen(context: viewModel.context)
.previewDisplayName("Screen")
Text("Timeline view")
.sheet(isPresented: .constant(true)) {
EmojiPickerScreen(context: viewModel.context)
}
.previewDisplayName("Sheet")
}
}

View File

@ -22,7 +22,7 @@ struct InviteUsersScreen: View {
var body: some View {
mainContent
.elementFormStyle()
.compoundForm()
.scrollDismissesKeyboard(.immediately)
.navigationTitle(L10n.screenCreateRoomAddPeopleTitle)
.navigationBarTitleDisplayMode(.inline)
@ -86,8 +86,7 @@ struct InviteUsersScreen: View {
Text(title)
}
}
.listRowSeparator(.automatic)
.formSectionStyle()
.compoundFormSection()
} else {
Section.empty
}

View File

@ -27,10 +27,9 @@ struct MessageForwardingScreen: View {
.buttonStyle(FormButtonStyle(accessory: .singleSelection(isSelected: context.viewState.selectedRoomID == room.id)))
}
}
.formSectionStyle()
.compoundFormSection()
}
.listRowSeparator(.automatic)
.elementFormStyle()
.compoundForm()
.navigationTitle(L10n.commonForwardMessage)
.navigationBarTitleDisplayMode(.inline)
.toolbar {

View File

@ -0,0 +1,28 @@
//
// Copyright 2023 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import SwiftUI
/// The background gradient shown on the launch, splash and onboarding screens.
struct OnboardingBackgroundImage: View {
var body: some View {
Image(asset: Asset.Images.launchBackground)
.resizable()
.scaledToFill()
.ignoresSafeArea()
.accessibilityHidden(true)
}
}

View File

@ -1,72 +0,0 @@
//
// Copyright 2023 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import DesignKit
import SwiftUI
/// A glossy animated background view designed for the onboarding screen
struct OnboardingBackgroundView: View {
@Environment(\.colorScheme) private var colorScheme
var isAnimated = true
@State private var factor = 0.0
@State private var isReversed = false
private let step = 0.001
private let timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
var body: some View {
GeometryReader { geometry in
ZStack {
Image(asset: Asset.Images.onboardingBackgroundPart1)
.position(x: geometry.size.width * 0.125 - factor * geometry.size.width * 0.25, y: (1.0 - factor) * geometry.size.height * 0.55)
Image(asset: Asset.Images.onboardingBackgroundPart2)
.position(x: geometry.size.width * 1.05, y: factor * geometry.size.height * 0.45)
Image(asset: Asset.Images.onboardingBackgroundPart3)
.position(x: factor * geometry.size.width, y: geometry.size.height * 1.05 - factor * geometry.size.height * 0.08)
}
.frame(width: geometry.size.width, height: geometry.size.height)
.onReceive(timer) { _ in
guard isAnimated else { return }
if isReversed {
guard factor > 0 else {
isReversed = false
factor = step
return
}
factor -= step
} else {
guard factor < 1 else {
isReversed = true
factor = 1 - step
return
}
factor += 0.001
}
}
}
}
}
struct OnboardingBackgroundView_Previews: PreviewProvider {
static var previews: some View {
OnboardingBackgroundView()
}
}

View File

@ -24,10 +24,6 @@ struct OnboardingScreen: View {
@ObservedObject var context: OnboardingViewModel.Context
var body: some View {
ZStack {
OnboardingBackgroundView(isAnimated: !Tests.isRunningUITests)
.accessibilityHidden(true)
GeometryReader { geometry in
VStack(alignment: .leading) {
Spacer()
@ -37,8 +33,6 @@ struct OnboardingScreen: View {
.frame(width: geometry.size.width)
.accessibilityIdentifier(A11yIdentifiers.onboardingScreen.hidden)
Spacer()
buttons
.frame(width: geometry.size.width)
.padding(.bottom, UIConstants.actionButtonBottomPadding)
@ -50,31 +44,30 @@ struct OnboardingScreen: View {
.frame(maxHeight: .infinity)
}
.navigationBarHidden(true)
.background {
OnboardingBackgroundImage()
}
}
var content: some View {
VStack {
Spacer()
if verticalSizeClass == .regular {
Spacer()
Image(Asset.Images.onboardingAppLogo.name)
.resizable()
.scaledToFit()
.padding(60)
Image(asset: Asset.Images.launchLogo)
.accessibilityHidden(true)
}
Spacer()
VStack(spacing: 8) {
Spacer()
Text(L10n.screenOnboardingWelcomeTitle)
.font(.compound.headingLGBold)
.foregroundColor(.compound.textPrimary)
.multilineTextAlignment(.center)
Text(L10n.screenOnboardingWelcomeSubtitle(InfoPlistReader.main.bundleDisplayName))
Text(L10n.screenOnboardingWelcomeMessage)
.font(.compound.bodyLG)
.foregroundColor(.compound.textSecondary)
.multilineTextAlignment(.center)

View File

@ -18,12 +18,24 @@ import SwiftUI
class SplashScreenCoordinator: CoordinatorProtocol {
func toPresentable() -> AnyView {
AnyView(
ZStack {
Image(asset: Asset.Images.onboardingAppLogo)
.renderingMode(.original)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
)
AnyView(SplashScreen())
}
}
/// The app's splash screen. This screen is shown after the LaunchScreen
/// until the app is ready to show the relevant coordinator. The design of
/// these 2 screens are matched.
struct SplashScreen: View {
var body: some View {
Image(asset: Asset.Images.launchLogo)
.accessibilityHidden(true)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background { OnboardingBackgroundImage() }
}
}
struct SplashScreen_Previews: PreviewProvider {
static var previews: some View {
SplashScreen()
}
}

View File

@ -31,7 +31,7 @@ struct RoomDetailsEditScreen: View {
nameSection
topicSection
}
.elementFormStyle()
.compoundForm()
.scrollDismissesKeyboard(.immediately)
.navigationTitle(L10n.screenRoomDetailsEditRoomTitle)
.navigationBarTitleDisplayMode(.inline)
@ -98,9 +98,9 @@ struct RoomDetailsEditScreen: View {
.clipShape(RoundedRectangle(cornerRadius: 8))
} header: {
Text(L10n.commonRoomName)
.formSectionHeader()
.compoundFormSectionHeader()
}
.formSectionStyle()
.compoundFormSection()
}
private var topicSection: some View {
@ -118,9 +118,9 @@ struct RoomDetailsEditScreen: View {
.lineLimit(3...)
} header: {
Text(L10n.commonTopic)
.formSectionHeader()
.compoundFormSectionHeader()
}
.formSectionStyle()
.compoundFormSection()
}
private var avatarOverlayIcon: some View {

View File

@ -43,7 +43,7 @@ struct RoomDetailsScreen: View {
leaveRoomSection
}
.elementFormStyle()
.compoundForm()
.alert(item: $context.alertInfo)
.alert(item: $context.leaveRoomAlertItem,
actions: leaveRoomAlertActions,
@ -129,9 +129,9 @@ struct RoomDetailsScreen: View {
}
} header: {
Text(L10n.commonTopic)
.formSectionHeader()
.compoundFormSectionHeader()
}
.formSectionStyle()
.compoundFormSection()
}
}
@ -159,9 +159,8 @@ struct RoomDetailsScreen: View {
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.invite)
}
}
.listRowSeparatorTint(.compound.borderDisabled)
.buttonStyle(FormButtonStyle(accessory: .navigationLink))
.formSectionStyle()
.compoundFormSection()
.foregroundColor(.compound.textPrimary)
}
@ -182,9 +181,9 @@ struct RoomDetailsScreen: View {
.labelStyle(FormRowLabelStyle(alignment: .top))
} header: {
Text(L10n.commonSecurity)
.formSectionHeader()
.compoundFormSectionHeader()
}
.formSectionStyle()
.compoundFormSection()
}
}
@ -197,7 +196,7 @@ struct RoomDetailsScreen: View {
}
.buttonStyle(FormButtonStyle(accessory: nil))
}
.formSectionStyle()
.compoundFormSection()
}
@ViewBuilder
@ -212,7 +211,7 @@ struct RoomDetailsScreen: View {
.buttonStyle(FormButtonStyle(accessory: context.viewState.isProcessingIgnoreRequest ? .progressView : nil))
.disabled(context.viewState.isProcessingIgnoreRequest)
}
.formSectionStyle()
.compoundFormSection()
}
@ViewBuilder

View File

@ -27,7 +27,7 @@ struct RoomMemberDetailsScreen: View {
blockUserSection
}
}
.elementFormStyle()
.compoundForm()
.alert(item: $context.ignoreUserAlert, actions: blockUserAlertActions, message: blockUserAlertMessage)
.alert(item: $context.alertInfo)
.track(screen: .user)
@ -66,7 +66,7 @@ struct RoomMemberDetailsScreen: View {
.buttonStyle(FormButtonStyle(accessory: context.viewState.isProcessingIgnoreRequest ? .progressView : nil))
.disabled(context.viewState.isProcessingIgnoreRequest)
}
.formSectionStyle()
.compoundFormSection()
}
private var blockUserButtonAction: RoomMemberDetailsScreenViewAction {

View File

@ -356,7 +356,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
]
if timelineItem is EventBasedMessageTimelineItemProtocol {
actions.append(contentsOf: [.forward(itemID: itemId), .copy, .quote])
actions.append(contentsOf: [.forward(itemID: itemId), .copy])
}
actions.append(.copyPermalink)
@ -403,13 +403,6 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
state.bindings.composerFocused = true
state.bindings.composerText = messageTimelineItem.body
setComposerMode(.edit(originalItemId: messageTimelineItem.id))
case .quote:
guard let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol else {
return
}
state.bindings.composerFocused = true
state.bindings.composerText = "> \(messageTimelineItem.body)\n\n"
case .copyPermalink:
do {
let permalink = try PermalinkBuilder.permalinkTo(eventIdentifier: eventTimelineItem.id, roomIdentifier: timelineController.roomID)

View File

@ -0,0 +1,96 @@
//
// Copyright 2023 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import SwiftUI
struct LongPressWithFeedback: ViewModifier {
let action: () -> Void
@State private var isLongPressing = false
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
func body(content: Content) -> some View {
content
.scaleEffect(x: isLongPressing ? 0.93 : 1,
y: isLongPressing ? 0.93 : 1)
.animation(isLongPressing ? .spring(response: 0.8).delay(0.2) : .spring(response: 0.2),
value: isLongPressing)
.onLongPressGesture(minimumDuration: 0.25) {
action()
feedbackGenerator.impactOccurred()
} onPressingChanged: { isPressing in
isLongPressing = isPressing
if isPressing {
feedbackGenerator.prepare()
}
}
}
}
extension View {
func longPressWithFeedback(action: @escaping () -> Void) -> some View {
modifier(LongPressWithFeedback(action: action))
}
}
struct FakeContextMenu_Previews: PreviewProvider {
static var previews: some View { Preview() }
struct Preview: View {
private let viewModel = RoomScreenViewModel.mock
@State private var isPresentingSheet = false
var body: some View {
NavigationStack {
ScrollView {
VStack(alignment: .leading) {
mockBubble("This is a message from somebody with a couple of lines of text.")
.longPressWithFeedback { isPresentingSheet = true }
mockBubble("Short message")
.longPressWithFeedback { isPresentingSheet = true }
mockBubble("How are you today? The sun is shining here and its very hot ☀️☀️☀️")
.longPressWithFeedback { isPresentingSheet = true }
mockBubble("I'm a fake!")
.contextMenu {
Button("Copy") { }
Button("Reply") { }
Button("Remove") { }
}
}
.padding()
}
.navigationTitle("Work chat")
.navigationBarTitleDisplayMode(.inline)
}
.sheet(isPresented: $isPresentingSheet) {
Text("Long pressed!")
.presentationDetents([.medium])
}
.environmentObject(viewModel.context)
}
func mockBubble(_ body: String) -> some View {
Text(body)
.padding(.horizontal, 12)
.padding(.vertical, 4)
.background(Color.compound._bgBubbleOutgoing, in: RoundedRectangle(cornerRadius: 12))
.onTapGesture { /* Fix long press gesture blocking the scroll view */ }
}
}
}

View File

@ -21,8 +21,6 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
@EnvironmentObject private var context: RoomScreenViewModel.Context
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
let timelineItem: EventBasedTimelineItemProtocol
@ViewBuilder let content: () -> Content
@ -116,13 +114,8 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
}
// We need a tap gesture before this long one so that it doesn't
// steal away the gestures from the scroll view
.onLongPressGesture(minimumDuration: 0.25) {
.longPressWithFeedback {
context.send(viewAction: .timelineItemMenu(itemID: timelineItem.id))
feedbackGenerator.impactOccurred()
} onPressingChanged: { pressing in
if pressing {
feedbackGenerator.prepare()
}
}
.padding(.top, messageBubbleTopPadding)
}

View File

@ -33,7 +33,6 @@ struct TimelineItemMenuActions {
enum TimelineItemMenuAction: Identifiable, Hashable {
case copy
case edit
case quote
case copyPermalink
case redact
case reply
@ -182,10 +181,6 @@ public struct TimelineItemMenu: View {
Button { send(action) } label: {
MenuLabel(title: L10n.actionEdit, systemImageName: "pencil.line")
}
case .quote:
Button { send(action) } label: {
MenuLabel(title: L10n.actionQuote, systemImageName: "quote.bubble")
}
case .copyPermalink:
Button { send(action) } label: {
MenuLabel(title: L10n.actionCopyLinkToMessage, systemImageName: "link")

View File

@ -65,7 +65,7 @@ struct DeveloperOptionsScreen: View {
}
}
.overlay(effectsView)
.elementFormStyle()
.compoundForm()
.navigationTitle(L10n.commonDeveloperOptions)
.navigationBarTitleDisplayMode(.inline)
}

View File

@ -28,13 +28,13 @@ struct StartChatScreen: View {
searchContent
}
}
.elementFormStyle()
.compoundForm()
.track(screen: .startChat)
.scrollDismissesKeyboard(.immediately)
.navigationTitle(L10n.actionStartChat)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
ToolbarItem(placement: .cancellationAction) {
closeButton
}
}
@ -73,7 +73,7 @@ struct StartChatScreen: View {
}
.buttonStyle(FormButtonStyle(accessory: .navigationLink))
}
.formSectionStyle()
.compoundFormSection()
}
private var inviteFriendsSection: some View {
@ -84,7 +84,7 @@ struct StartChatScreen: View {
.buttonStyle(FormButtonStyle())
.accessibilityIdentifier(A11yIdentifiers.startChatScreen.inviteFriends)
}
.formSectionStyle()
.compoundFormSection()
}
@ViewBuilder
@ -102,8 +102,7 @@ struct StartChatScreen: View {
Text(title)
}
}
.listRowSeparator(.automatic)
.formSectionStyle()
.compoundFormSection()
} else {
Section.empty
}

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@ -15,16 +15,34 @@
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Images/LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="RH0-av-APO">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Images/LaunchLogo" translatesAutoresizingMaskIntoConstraints="NO" id="c15-l5-nD6">
<rect key="frame" x="96" y="344" width="222" height="222"/>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="RH0-av-APO" secondAttribute="bottom" id="CRY-uh-cTI"/>
<constraint firstItem="RH0-av-APO" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="Jvy-2m-VFg"/>
<constraint firstItem="RH0-av-APO" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="KvB-au-rcv"/>
<constraint firstItem="c15-l5-nD6" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="NZy-ab-uVa"/>
<constraint firstItem="c15-l5-nD6" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" id="W8Y-GD-lIo"/>
<constraint firstAttribute="trailing" secondItem="RH0-av-APO" secondAttribute="trailing" id="hbN-2h-ALU"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
<point key="canvasLocation" x="52.173913043478265" y="375"/>
</scene>
</scenes>
<resources>
<image name="Images/LaunchBackground" width="390" height="844"/>
<image name="Images/LaunchLogo" width="222" height="222"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>

View File

@ -53,7 +53,7 @@ packages:
minorVersion: 5.13.0
Compound:
url: https://github.com/vector-im/compound-ios
revision: e8b35fdd8c4008079dfce203e63bf7a05582d7b9
revision: d1a28b8a311e33ddb517d10391037f1547a3c7b6
# path: ../compound-ios
Algorithms:
url: https://github.com/apple/swift-algorithms