Send current user location (#1272)
* add new asset for location, add logic for sharing user current location * work on default zoom and auth for location * add attribution button * fix attribution button position, fix isSharingUserLocation * Add NSLocationWhenInUseUsageDescription back * Fix initial animation * change map logo and attribution position * Add annotation just in the setup * add errors and alert for map vies * location unit test * add unit test for location sharing * add changelog * Update ElementX/Sources/Other/MapLibre/MapLibreMapView.swift Co-authored-by: Alfonso Grillo <alfogrillo@gmail.com> * add comments and minor parameters refactor * Update ElementX/Sources/Screens/LocationSharing/StaticLocationScreenCoordinator.swift Co-authored-by: Mauro <34335419+Velin92@users.noreply.github.com> * Update ElementX/Sources/Screens/LocationSharing/StaticLocationScreenViewModel.swift Co-authored-by: Mauro <34335419+Velin92@users.noreply.github.com> * Sort assets * Cleanup * Cleanup * Fix error localizations * Fix tests --------- Co-authored-by: Alfonso Grillo <alfogrillo@gmail.com> Co-authored-by: Mauro <34335419+Velin92@users.noreply.github.com>
This commit is contained in:
@@ -4,8 +4,7 @@
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
runPostActionsOnFailure = "NO">
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
@@ -30,12 +29,6 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
codeCoverageEnabled = "YES"
|
||||
onlyGenerateCoverageForSpecifiedTargets = "YES">
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
default = "YES"
|
||||
reference = "container:UnitTests/SupportingFiles/UnitTests.xctestplan">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
@@ -45,10 +38,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
</Testables>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
<CodeCoverageTargets>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
@@ -58,6 +47,12 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</CodeCoverageTargets>
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
reference = "container:UnitTests/SupportingFiles/UnitTests.xctestplan"
|
||||
default = "YES">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@@ -79,8 +74,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "RUST_BACKTRACE"
|
||||
@@ -120,8 +113,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
|
||||
22
ElementX/Resources/Assets.xcassets/images/location/location-pointer-full.imageset/Contents.json
vendored
Normal file
22
ElementX/Resources/Assets.xcassets/images/location/location-pointer-full.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "location-pointer-full.pdf",
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "location-pointer-full-dark.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 40.000000 40.000000 ]
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
0.062745 0.074510 0.090196 scn
|
||||
0.000000 34.000000 m
|
||||
0.000000 37.313709 2.686292 40.000000 6.000000 40.000000 c
|
||||
34.000000 40.000000 l
|
||||
37.313709 40.000000 40.000000 37.313709 40.000000 34.000000 c
|
||||
40.000000 6.000000 l
|
||||
40.000000 2.686291 37.313709 0.000000 34.000000 0.000000 c
|
||||
5.999999 0.000000 l
|
||||
2.686291 0.000000 0.000000 2.686291 0.000000 6.000000 c
|
||||
0.000000 34.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 9.000000 9.000000 cm
|
||||
0.921569 0.933333 0.949020 scn
|
||||
11.000000 15.000000 m
|
||||
8.790000 15.000000 7.000000 13.210000 7.000000 11.000000 c
|
||||
7.000000 8.790000 8.790000 7.000000 11.000000 7.000000 c
|
||||
13.210000 7.000000 15.000000 8.790000 15.000000 11.000000 c
|
||||
15.000000 13.210000 13.210000 15.000000 11.000000 15.000000 c
|
||||
h
|
||||
19.940001 12.000000 m
|
||||
19.480001 16.170000 16.170000 19.480000 12.000000 19.940001 c
|
||||
12.000000 21.000000 l
|
||||
12.000000 21.549999 11.550000 22.000000 11.000000 22.000000 c
|
||||
10.450000 22.000000 10.000000 21.549999 10.000000 21.000000 c
|
||||
10.000000 19.940001 l
|
||||
5.830000 19.480000 2.520000 16.170000 2.060000 12.000000 c
|
||||
1.000000 12.000000 l
|
||||
0.450000 12.000000 0.000000 11.550000 0.000000 11.000000 c
|
||||
0.000000 10.450000 0.450000 10.000000 1.000000 10.000000 c
|
||||
2.060000 10.000000 l
|
||||
2.520000 5.830000 5.830000 2.519999 10.000000 2.059999 c
|
||||
10.000000 1.000000 l
|
||||
10.000000 0.450001 10.450000 0.000000 11.000000 0.000000 c
|
||||
11.550000 0.000000 12.000000 0.450001 12.000000 1.000000 c
|
||||
12.000000 2.059999 l
|
||||
16.170000 2.519999 19.480001 5.830000 19.940001 10.000000 c
|
||||
21.000000 10.000000 l
|
||||
21.549999 10.000000 22.000000 10.450000 22.000000 11.000000 c
|
||||
22.000000 11.550000 21.549999 12.000000 21.000000 12.000000 c
|
||||
19.940001 12.000000 l
|
||||
19.940001 12.000000 l
|
||||
h
|
||||
11.000000 4.000000 m
|
||||
7.130000 4.000000 4.000000 7.130000 4.000000 11.000000 c
|
||||
4.000000 14.870000 7.130000 18.000000 11.000000 18.000000 c
|
||||
14.870000 18.000000 18.000000 14.870000 18.000000 11.000000 c
|
||||
18.000000 7.130000 14.870000 4.000000 11.000000 4.000000 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
2028
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 40.000000 40.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 34.000000 m
|
||||
0.000000 37.313709 2.686292 40.000000 6.000000 40.000000 c
|
||||
34.000000 40.000000 l
|
||||
37.313709 40.000000 40.000000 37.313709 40.000000 34.000000 c
|
||||
40.000000 6.000000 l
|
||||
40.000000 2.686291 37.313709 0.000000 34.000000 0.000000 c
|
||||
5.999999 0.000000 l
|
||||
2.686291 0.000000 0.000000 2.686291 0.000000 6.000000 c
|
||||
0.000000 34.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
468
|
||||
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
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
46
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 40.000000 40.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
|
||||
0000002286 00000 n
|
||||
0000002309 00000 n
|
||||
0000003025 00000 n
|
||||
0000003047 00000 n
|
||||
0000003345 00000 n
|
||||
0000003447 00000 n
|
||||
0000003468 00000 n
|
||||
0000003641 00000 n
|
||||
0000003715 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
3775
|
||||
%%EOF
|
||||
@@ -0,0 +1,189 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 40.000000 40.000000 ]
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
0.000000 34.000000 m
|
||||
0.000000 37.313709 2.686292 40.000000 6.000000 40.000000 c
|
||||
34.000000 40.000000 l
|
||||
37.313709 40.000000 40.000000 37.313709 40.000000 34.000000 c
|
||||
40.000000 6.000000 l
|
||||
40.000000 2.686291 37.313709 0.000000 34.000000 0.000000 c
|
||||
5.999999 0.000000 l
|
||||
2.686291 0.000000 0.000000 2.686291 0.000000 6.000000 c
|
||||
0.000000 34.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 9.000000 9.000000 cm
|
||||
0.105882 0.113725 0.133333 scn
|
||||
11.000000 15.000000 m
|
||||
8.790000 15.000000 7.000000 13.210000 7.000000 11.000000 c
|
||||
7.000000 8.790000 8.790000 7.000000 11.000000 7.000000 c
|
||||
13.210000 7.000000 15.000000 8.790000 15.000000 11.000000 c
|
||||
15.000000 13.210000 13.210000 15.000000 11.000000 15.000000 c
|
||||
h
|
||||
19.940001 12.000000 m
|
||||
19.480001 16.170000 16.170000 19.480000 12.000000 19.940001 c
|
||||
12.000000 21.000000 l
|
||||
12.000000 21.549999 11.550000 22.000000 11.000000 22.000000 c
|
||||
10.450000 22.000000 10.000000 21.549999 10.000000 21.000000 c
|
||||
10.000000 19.940001 l
|
||||
5.830000 19.480000 2.520000 16.170000 2.060000 12.000000 c
|
||||
1.000000 12.000000 l
|
||||
0.450000 12.000000 0.000000 11.550000 0.000000 11.000000 c
|
||||
0.000000 10.450000 0.450000 10.000000 1.000000 10.000000 c
|
||||
2.060000 10.000000 l
|
||||
2.520000 5.830000 5.830000 2.519999 10.000000 2.059999 c
|
||||
10.000000 1.000000 l
|
||||
10.000000 0.450001 10.450000 0.000000 11.000000 0.000000 c
|
||||
11.550000 0.000000 12.000000 0.450001 12.000000 1.000000 c
|
||||
12.000000 2.059999 l
|
||||
16.170000 2.519999 19.480001 5.830000 19.940001 10.000000 c
|
||||
21.000000 10.000000 l
|
||||
21.549999 10.000000 22.000000 10.450000 22.000000 11.000000 c
|
||||
22.000000 11.550000 21.549999 12.000000 21.000000 12.000000 c
|
||||
19.940001 12.000000 l
|
||||
19.940001 12.000000 l
|
||||
h
|
||||
11.000000 4.000000 m
|
||||
7.130000 4.000000 4.000000 7.130000 4.000000 11.000000 c
|
||||
4.000000 14.870000 7.130000 18.000000 11.000000 18.000000 c
|
||||
14.870000 18.000000 18.000000 14.870000 18.000000 11.000000 c
|
||||
18.000000 7.130000 14.870000 4.000000 11.000000 4.000000 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
2028
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 40.000000 40.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 34.000000 m
|
||||
0.000000 37.313709 2.686292 40.000000 6.000000 40.000000 c
|
||||
34.000000 40.000000 l
|
||||
37.313709 40.000000 40.000000 37.313709 40.000000 34.000000 c
|
||||
40.000000 6.000000 l
|
||||
40.000000 2.686291 37.313709 0.000000 34.000000 0.000000 c
|
||||
5.999999 0.000000 l
|
||||
2.686291 0.000000 0.000000 2.686291 0.000000 6.000000 c
|
||||
0.000000 34.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
468
|
||||
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
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
46
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 40.000000 40.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
|
||||
0000002286 00000 n
|
||||
0000002309 00000 n
|
||||
0000003025 00000 n
|
||||
0000003047 00000 n
|
||||
0000003345 00000 n
|
||||
0000003447 00000 n
|
||||
0000003468 00000 n
|
||||
0000003641 00000 n
|
||||
0000003715 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
3775
|
||||
%%EOF
|
||||
22
ElementX/Resources/Assets.xcassets/images/location/location-pointer.imageset/Contents.json
vendored
Normal file
22
ElementX/Resources/Assets.xcassets/images/location/location-pointer.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "location-pointer.pdf",
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "location-pointer-dark.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 40.000000 40.000000 ]
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
0.062745 0.074510 0.090196 scn
|
||||
0.000000 34.000000 m
|
||||
0.000000 37.313709 2.686292 40.000000 6.000000 40.000000 c
|
||||
34.000000 40.000000 l
|
||||
37.313709 40.000000 40.000000 37.313709 40.000000 34.000000 c
|
||||
40.000000 6.000000 l
|
||||
40.000000 2.686291 37.313709 0.000000 34.000000 0.000000 c
|
||||
5.999999 0.000000 l
|
||||
2.686291 0.000000 0.000000 2.686291 0.000000 6.000000 c
|
||||
0.000000 34.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 9.049805 9.049805 cm
|
||||
0.921569 0.933333 0.949020 scn
|
||||
10.950000 0.000391 m
|
||||
10.666667 0.000391 10.429167 0.096224 10.237500 0.287889 c
|
||||
10.045834 0.479557 9.950000 0.717056 9.950000 1.000391 c
|
||||
9.950000 2.000391 l
|
||||
7.866667 2.233725 6.079167 3.096224 4.587500 4.587891 c
|
||||
3.095833 6.079557 2.233333 7.867057 2.000000 9.950391 c
|
||||
1.000000 9.950391 l
|
||||
0.716667 9.950391 0.479167 10.046224 0.287500 10.237890 c
|
||||
0.095833 10.429557 0.000000 10.667057 0.000000 10.950391 c
|
||||
0.000000 11.233724 0.095833 11.471224 0.287500 11.662890 c
|
||||
0.479167 11.854557 0.716667 11.950391 1.000000 11.950391 c
|
||||
2.000000 11.950391 l
|
||||
2.233333 14.033724 3.095833 15.821224 4.587500 17.312891 c
|
||||
6.079167 18.804558 7.866667 19.667057 9.950000 19.900391 c
|
||||
9.950000 20.900391 l
|
||||
9.950000 21.183723 10.045834 21.421225 10.237500 21.612890 c
|
||||
10.429167 21.804558 10.666667 21.900391 10.950000 21.900391 c
|
||||
11.233334 21.900391 11.470834 21.804558 11.662500 21.612890 c
|
||||
11.854167 21.421225 11.950000 21.183723 11.950000 20.900391 c
|
||||
11.950000 19.900391 l
|
||||
14.033334 19.667057 15.820833 18.804558 17.312500 17.312891 c
|
||||
18.804167 15.821224 19.666666 14.033724 19.900000 11.950391 c
|
||||
20.900000 11.950391 l
|
||||
21.183334 11.950391 21.420834 11.854557 21.612501 11.662890 c
|
||||
21.804167 11.471224 21.900000 11.233724 21.900000 10.950391 c
|
||||
21.900000 10.667057 21.804167 10.429557 21.612501 10.237890 c
|
||||
21.420834 10.046224 21.183334 9.950391 20.900000 9.950391 c
|
||||
19.900000 9.950391 l
|
||||
19.666666 7.867057 18.804167 6.079557 17.312500 4.587891 c
|
||||
15.820833 3.096224 14.033334 2.233725 11.950000 2.000391 c
|
||||
11.950000 1.000391 l
|
||||
11.950000 0.717056 11.854167 0.479557 11.662500 0.287889 c
|
||||
11.470834 0.096224 11.233334 0.000391 10.950000 0.000391 c
|
||||
h
|
||||
10.950000 3.950390 m
|
||||
12.883333 3.950390 14.533334 4.633724 15.900001 6.000390 c
|
||||
17.266666 7.367057 17.950001 9.017057 17.950001 10.950391 c
|
||||
17.950001 12.883724 17.266666 14.533724 15.900001 15.900391 c
|
||||
14.533334 17.267057 12.883333 17.950390 10.950000 17.950390 c
|
||||
9.016666 17.950390 7.366667 17.267057 6.000000 15.900391 c
|
||||
4.633333 14.533724 3.950000 12.883724 3.950000 10.950391 c
|
||||
3.950000 9.017057 4.633333 7.367057 6.000000 6.000390 c
|
||||
7.366667 4.633724 9.016666 3.950390 10.950000 3.950390 c
|
||||
h
|
||||
10.950000 6.950391 m
|
||||
9.850000 6.950391 8.908334 7.342057 8.125000 8.125390 c
|
||||
7.341667 8.908724 6.950000 9.850390 6.950000 10.950391 c
|
||||
6.950000 12.050390 7.341667 12.992057 8.125000 13.775391 c
|
||||
8.908334 14.558723 9.850000 14.950390 10.950000 14.950390 c
|
||||
12.050000 14.950390 12.991667 14.558723 13.775001 13.775391 c
|
||||
14.558333 12.992057 14.950000 12.050390 14.950000 10.950391 c
|
||||
14.950000 9.850390 14.558333 8.908724 13.775001 8.125390 c
|
||||
12.991667 7.342057 12.050000 6.950391 10.950000 6.950391 c
|
||||
h
|
||||
10.950000 8.950391 m
|
||||
11.500000 8.950391 11.970834 9.146224 12.362500 9.537890 c
|
||||
12.754167 9.929557 12.950000 10.400391 12.950000 10.950391 c
|
||||
12.950000 11.500390 12.754167 11.971224 12.362500 12.362890 c
|
||||
11.970834 12.754558 11.500000 12.950391 10.950000 12.950391 c
|
||||
10.400001 12.950391 9.929167 12.754558 9.537500 12.362890 c
|
||||
9.145833 11.971224 8.950000 11.500390 8.950000 10.950391 c
|
||||
8.950000 10.400391 9.145833 9.929557 9.537500 9.537890 c
|
||||
9.929167 9.146224 10.400001 8.950391 10.950000 8.950391 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
3685
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 40.000000 40.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 34.000000 m
|
||||
0.000000 37.313709 2.686292 40.000000 6.000000 40.000000 c
|
||||
34.000000 40.000000 l
|
||||
37.313709 40.000000 40.000000 37.313709 40.000000 34.000000 c
|
||||
40.000000 6.000000 l
|
||||
40.000000 2.686291 37.313709 0.000000 34.000000 0.000000 c
|
||||
5.999999 0.000000 l
|
||||
2.686291 0.000000 0.000000 2.686291 0.000000 6.000000 c
|
||||
0.000000 34.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
468
|
||||
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
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
46
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 40.000000 40.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
|
||||
0000003943 00000 n
|
||||
0000003966 00000 n
|
||||
0000004682 00000 n
|
||||
0000004704 00000 n
|
||||
0000005002 00000 n
|
||||
0000005104 00000 n
|
||||
0000005125 00000 n
|
||||
0000005298 00000 n
|
||||
0000005372 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
5432
|
||||
%%EOF
|
||||
218
ElementX/Resources/Assets.xcassets/images/location/location-pointer.imageset/location-pointer.pdf
vendored
Normal file
218
ElementX/Resources/Assets.xcassets/images/location/location-pointer.imageset/location-pointer.pdf
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 40.000000 40.000000 ]
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
0.000000 34.000000 m
|
||||
0.000000 37.313709 2.686292 40.000000 6.000000 40.000000 c
|
||||
34.000000 40.000000 l
|
||||
37.313709 40.000000 40.000000 37.313709 40.000000 34.000000 c
|
||||
40.000000 6.000000 l
|
||||
40.000000 2.686291 37.313709 0.000000 34.000000 0.000000 c
|
||||
5.999999 0.000000 l
|
||||
2.686291 0.000000 0.000000 2.686291 0.000000 6.000000 c
|
||||
0.000000 34.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 9.049805 9.049927 cm
|
||||
0.105882 0.113725 0.133333 scn
|
||||
10.950000 0.000025 m
|
||||
10.666666 0.000025 10.429167 0.095856 10.237500 0.287523 c
|
||||
10.045834 0.479191 9.950000 0.716692 9.950000 1.000025 c
|
||||
9.950000 2.000025 l
|
||||
7.866666 2.233358 6.079167 3.095858 4.587500 4.587524 c
|
||||
3.095833 6.079191 2.233333 7.866692 2.000000 9.950025 c
|
||||
1.000000 9.950025 l
|
||||
0.716667 9.950025 0.479167 10.045857 0.287500 10.237524 c
|
||||
0.095833 10.429191 0.000000 10.666691 0.000000 10.950025 c
|
||||
0.000000 11.233358 0.095833 11.470858 0.287500 11.662524 c
|
||||
0.479167 11.854191 0.716667 11.950025 1.000000 11.950025 c
|
||||
2.000000 11.950025 l
|
||||
2.233333 14.033358 3.095833 15.820858 4.587500 17.312525 c
|
||||
6.079167 18.804192 7.866666 19.666691 9.950000 19.900024 c
|
||||
9.950000 20.900024 l
|
||||
9.950000 21.183357 10.045834 21.420858 10.237500 21.612524 c
|
||||
10.429167 21.804192 10.666666 21.900024 10.950000 21.900024 c
|
||||
11.233334 21.900024 11.470834 21.804192 11.662500 21.612524 c
|
||||
11.854167 21.420858 11.950000 21.183357 11.950000 20.900024 c
|
||||
11.950000 19.900024 l
|
||||
14.033333 19.666691 15.820833 18.804192 17.312500 17.312525 c
|
||||
18.804167 15.820858 19.666666 14.033358 19.900000 11.950025 c
|
||||
20.900000 11.950025 l
|
||||
21.183332 11.950025 21.420834 11.854191 21.612501 11.662524 c
|
||||
21.804169 11.470858 21.900000 11.233358 21.900000 10.950025 c
|
||||
21.900000 10.666691 21.804169 10.429191 21.612501 10.237524 c
|
||||
21.420834 10.045857 21.183332 9.950025 20.900000 9.950025 c
|
||||
19.900000 9.950025 l
|
||||
19.666666 7.866692 18.804167 6.079191 17.312500 4.587524 c
|
||||
15.820833 3.095858 14.033333 2.233358 11.950000 2.000025 c
|
||||
11.950000 1.000025 l
|
||||
11.950000 0.716692 11.854167 0.479191 11.662500 0.287523 c
|
||||
11.470834 0.095856 11.233334 0.000025 10.950000 0.000025 c
|
||||
h
|
||||
10.950000 3.950024 m
|
||||
12.883333 3.950024 14.533334 4.633358 15.900001 6.000024 c
|
||||
17.266666 7.366691 17.950001 9.016691 17.950001 10.950025 c
|
||||
17.950001 12.883358 17.266666 14.533358 15.900001 15.900024 c
|
||||
14.533334 17.266691 12.883333 17.950024 10.950000 17.950024 c
|
||||
9.016666 17.950024 7.366667 17.266691 6.000000 15.900024 c
|
||||
4.633333 14.533358 3.950000 12.883358 3.950000 10.950025 c
|
||||
3.950000 9.016691 4.633333 7.366691 6.000000 6.000024 c
|
||||
7.366667 4.633358 9.016666 3.950024 10.950000 3.950024 c
|
||||
h
|
||||
10.950000 6.950025 m
|
||||
9.849999 6.950025 8.908334 7.341690 8.125000 8.125024 c
|
||||
7.341667 8.908358 6.950000 9.850024 6.950000 10.950025 c
|
||||
6.950000 12.050025 7.341667 12.991691 8.125000 13.775024 c
|
||||
8.908334 14.558357 9.849999 14.950024 10.950000 14.950024 c
|
||||
12.050000 14.950024 12.991667 14.558357 13.775001 13.775024 c
|
||||
14.558334 12.991691 14.950000 12.050025 14.950000 10.950025 c
|
||||
14.950000 9.850024 14.558334 8.908358 13.775001 8.125024 c
|
||||
12.991667 7.341690 12.050000 6.950025 10.950000 6.950025 c
|
||||
h
|
||||
10.950000 8.950025 m
|
||||
11.500000 8.950025 11.970834 9.145858 12.362500 9.537524 c
|
||||
12.754167 9.929191 12.950000 10.400024 12.950000 10.950025 c
|
||||
12.950000 11.500025 12.754167 11.970858 12.362500 12.362524 c
|
||||
11.970834 12.754190 11.500000 12.950025 10.950000 12.950025 c
|
||||
10.400000 12.950025 9.929167 12.754190 9.537500 12.362524 c
|
||||
9.145834 11.970858 8.950000 11.500025 8.950000 10.950025 c
|
||||
8.950000 10.400024 9.145834 9.929191 9.537500 9.537524 c
|
||||
9.929167 9.145858 10.400000 8.950025 10.950000 8.950025 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
3685
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 40.000000 40.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 34.000000 m
|
||||
0.000000 37.313709 2.686292 40.000000 6.000000 40.000000 c
|
||||
34.000000 40.000000 l
|
||||
37.313709 40.000000 40.000000 37.313709 40.000000 34.000000 c
|
||||
40.000000 6.000000 l
|
||||
40.000000 2.686291 37.313709 0.000000 34.000000 0.000000 c
|
||||
5.999999 0.000000 l
|
||||
2.686291 0.000000 0.000000 2.686291 0.000000 6.000000 c
|
||||
0.000000 34.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
468
|
||||
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
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
46
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 40.000000 40.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
|
||||
0000003943 00000 n
|
||||
0000003966 00000 n
|
||||
0000004682 00000 n
|
||||
0000004704 00000 n
|
||||
0000005002 00000 n
|
||||
0000005104 00000 n
|
||||
0000005125 00000 n
|
||||
0000005298 00000 n
|
||||
0000005372 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
5432
|
||||
%%EOF
|
||||
@@ -139,10 +139,10 @@
|
||||
"emoji_picker_category_places" = "Travel & Places";
|
||||
"emoji_picker_category_symbols" = "Symbols";
|
||||
"error_failed_creating_the_permalink" = "Failed creating the permalink";
|
||||
"error_failed_loading_map" = "Element could not load the map. Please try again later.";
|
||||
"error_failed_loading_map" = "%1$@ could not load the map. Please try again later.";
|
||||
"error_failed_loading_messages" = "Failed loading messages";
|
||||
"error_failed_locating_user" = "Element could not access your location. Please try again later.";
|
||||
"error_missing_location_auth" = "Element does not have permission to access your location. You can enable access in Settings > Location";
|
||||
"error_failed_locating_user" = "%1$@ could not access your location. Please try again later.";
|
||||
"error_missing_location_auth" = "%1$@ does not have permission to access your location. You can enable access in Settings > Location";
|
||||
"error_no_compatible_app_found" = "No compatible app was found to handle this action.";
|
||||
"error_some_messages_have_not_been_sent" = "Some messages have not been sent";
|
||||
"error_unknown" = "Sorry, an error occurred";
|
||||
@@ -308,6 +308,8 @@
|
||||
"screen_room_reactions_show_more" = "Show more";
|
||||
"screen_room_retry_send_menu_send_again_action" = "Send again";
|
||||
"screen_room_retry_send_menu_title" = "Your message failed to send";
|
||||
"screen_room_timeline_add_reaction" = "Add emoji";
|
||||
"screen_room_timeline_less_reactions" = "Show less";
|
||||
"screen_roomlist_a11y_create_message" = "Create a new conversation or room";
|
||||
"screen_roomlist_main_space_title" = "All Chats";
|
||||
"screen_server_confirmation_change_server" = "Change account provider";
|
||||
|
||||
@@ -146,5 +146,19 @@
|
||||
<string>%1$d people</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>screen_room_timeline_more_reactions</key>
|
||||
<dict>
|
||||
<key>NSStringLocalizedFormatKey</key>
|
||||
<string>%#@COUNT@</string>
|
||||
<key>COUNT</key>
|
||||
<dict>
|
||||
<key>NSStringFormatSpecTypeKey</key>
|
||||
<string>NSStringPluralRuleType</string>
|
||||
<key>NSStringFormatValueTypeKey</key>
|
||||
<string>d</string>
|
||||
<key>other</key>
|
||||
<string>%1$d more</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -515,7 +515,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
_ = await self.roomProxy?.sendLocation(body: geoURI.bodyMessage,
|
||||
geoURI: geoURI,
|
||||
description: nil,
|
||||
zoomLevel: nil,
|
||||
zoomLevel: 15,
|
||||
assetType: isUserLocation ? .sender : .pin)
|
||||
self.navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ internal enum Asset {
|
||||
internal static let launchLogo = ImageAsset(name: "images/launch-logo")
|
||||
internal static let locationMarker = ImageAsset(name: "images/location-marker")
|
||||
internal static let locationPin = ImageAsset(name: "images/location-pin")
|
||||
internal static let locationPointerFull = ImageAsset(name: "images/location-pointer-full")
|
||||
internal static let locationPointer = ImageAsset(name: "images/location-pointer")
|
||||
internal static let timelineComposerSendMessage = ImageAsset(name: "images/timeline-composer-send-message")
|
||||
internal static let waitingGradient = ImageAsset(name: "images/waiting-gradient")
|
||||
}
|
||||
|
||||
@@ -308,14 +308,20 @@ public enum L10n {
|
||||
public static var emojiPickerCategorySymbols: String { return L10n.tr("Localizable", "emoji_picker_category_symbols") }
|
||||
/// Failed creating the permalink
|
||||
public static var errorFailedCreatingThePermalink: String { return L10n.tr("Localizable", "error_failed_creating_the_permalink") }
|
||||
/// Element could not load the map. Please try again later.
|
||||
public static var errorFailedLoadingMap: String { return L10n.tr("Localizable", "error_failed_loading_map") }
|
||||
/// %1$@ could not load the map. Please try again later.
|
||||
public static func errorFailedLoadingMap(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "error_failed_loading_map", String(describing: p1))
|
||||
}
|
||||
/// Failed loading messages
|
||||
public static var errorFailedLoadingMessages: String { return L10n.tr("Localizable", "error_failed_loading_messages") }
|
||||
/// Element could not access your location. Please try again later.
|
||||
public static var errorFailedLocatingUser: String { return L10n.tr("Localizable", "error_failed_locating_user") }
|
||||
/// Element does not have permission to access your location. You can enable access in Settings > Location
|
||||
public static var errorMissingLocationAuth: String { return L10n.tr("Localizable", "error_missing_location_auth") }
|
||||
/// %1$@ could not access your location. Please try again later.
|
||||
public static func errorFailedLocatingUser(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "error_failed_locating_user", String(describing: p1))
|
||||
}
|
||||
/// %1$@ does not have permission to access your location. You can enable access in Settings > Location
|
||||
public static func errorMissingLocationAuth(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "error_missing_location_auth", String(describing: p1))
|
||||
}
|
||||
/// No compatible app was found to handle this action.
|
||||
public static var errorNoCompatibleAppFound: String { return L10n.tr("Localizable", "error_no_compatible_app_found") }
|
||||
/// Some messages have not been sent
|
||||
@@ -780,6 +786,14 @@ public enum L10n {
|
||||
public static var screenRoomRetrySendMenuSendAgainAction: String { return L10n.tr("Localizable", "screen_room_retry_send_menu_send_again_action") }
|
||||
/// Your message failed to send
|
||||
public static var screenRoomRetrySendMenuTitle: String { return L10n.tr("Localizable", "screen_room_retry_send_menu_title") }
|
||||
/// Add emoji
|
||||
public static var screenRoomTimelineAddReaction: String { return L10n.tr("Localizable", "screen_room_timeline_add_reaction") }
|
||||
/// Show less
|
||||
public static var screenRoomTimelineLessReactions: String { return L10n.tr("Localizable", "screen_room_timeline_less_reactions") }
|
||||
/// Plural format key: "%#@COUNT@"
|
||||
public static func screenRoomTimelineMoreReactions(_ p1: Int) -> String {
|
||||
return L10n.tr("Localizable", "screen_room_timeline_more_reactions", p1)
|
||||
}
|
||||
/// Create a new conversation or room
|
||||
public static var screenRoomlistA11yCreateMessage: String { return L10n.tr("Localizable", "screen_roomlist_a11y_create_message") }
|
||||
/// All Chats
|
||||
|
||||
@@ -20,15 +20,20 @@ import SwiftUI
|
||||
|
||||
struct MapLibreMapView: UIViewRepresentable {
|
||||
struct Options {
|
||||
/// The initial zoom level
|
||||
/// the final zoom level used when the first user location emit
|
||||
let zoomLevel: Double
|
||||
/// The initial zoom level used when the map it firstly loaded and the user location is not yet available, in case of annotations this property is not being used
|
||||
let initialZoomLevel: Double
|
||||
|
||||
/// The initial map center
|
||||
let mapCenter: CLLocationCoordinate2D?
|
||||
let mapCenter: CLLocationCoordinate2D
|
||||
|
||||
/// Map annotations
|
||||
let annotations: [LocationAnnotation]
|
||||
|
||||
init(zoomLevel: Double, mapCenter: CLLocationCoordinate2D? = nil, annotations: [LocationAnnotation] = []) {
|
||||
init(zoomLevel: Double, initialZoomLevel: Double, mapCenter: CLLocationCoordinate2D, annotations: [LocationAnnotation] = []) {
|
||||
self.zoomLevel = zoomLevel
|
||||
self.initialZoomLevel = initialZoomLevel
|
||||
self.mapCenter = mapCenter
|
||||
self.annotations = annotations
|
||||
}
|
||||
@@ -43,14 +48,16 @@ struct MapLibreMapView: UIViewRepresentable {
|
||||
let options: Options
|
||||
|
||||
/// Behavior mode of the current user's location, can be hidden, only shown and shown following the user
|
||||
var showsUserLocationMode: ShowUserLocationMode = .hide
|
||||
@Binding var showsUserLocationMode: ShowUserLocationMode
|
||||
|
||||
/// Bind view errors if any
|
||||
let error: Binding<MapLibreError?>
|
||||
@Binding var error: MapLibreError?
|
||||
|
||||
/// Coordinate of the center of the map
|
||||
@Binding var mapCenterCoordinate: CLLocationCoordinate2D?
|
||||
|
||||
@Binding var isLocationAuthorized: Bool?
|
||||
|
||||
/// Called when the user pan on the map
|
||||
var userDidPan: (() -> Void)?
|
||||
|
||||
@@ -59,23 +66,12 @@ struct MapLibreMapView: UIViewRepresentable {
|
||||
func makeUIView(context: Context) -> MGLMapView {
|
||||
let mapView = makeMapView()
|
||||
mapView.delegate = context.coordinator
|
||||
let panGesture = UIPanGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.didPan))
|
||||
panGesture.delegate = context.coordinator
|
||||
mapView.addGestureRecognizer(panGesture)
|
||||
setupMap(mapView: mapView, with: options)
|
||||
return mapView
|
||||
}
|
||||
|
||||
func updateUIView(_ mapView: MGLMapView, context: Context) {
|
||||
mapView.removeAllAnnotations()
|
||||
mapView.addAnnotations(options.annotations)
|
||||
|
||||
if colorScheme == .dark {
|
||||
mapView.styleURL = builder.dynamicMapURL(for: .dark)
|
||||
} else {
|
||||
mapView.styleURL = builder.dynamicMapURL(for: .light)
|
||||
}
|
||||
|
||||
mapView.styleURL = builder.dynamicMapURL(for: .init(colorScheme))
|
||||
showUserLocation(in: mapView)
|
||||
}
|
||||
|
||||
@@ -86,32 +82,36 @@ struct MapLibreMapView: UIViewRepresentable {
|
||||
// MARK: - Private
|
||||
|
||||
private func setupMap(mapView: MGLMapView, with options: Options) {
|
||||
mapView.zoomLevel = options.zoomLevel
|
||||
if let mapCenter = options.mapCenter {
|
||||
mapView.centerCoordinate = mapCenter
|
||||
}
|
||||
mapView.addAnnotations(options.annotations)
|
||||
mapView.zoomLevel = options.annotations.isEmpty ? options.initialZoomLevel : options.zoomLevel
|
||||
mapView.centerCoordinate = options.mapCenter
|
||||
}
|
||||
|
||||
private func makeMapView() -> MGLMapView {
|
||||
let mapView = MGLMapView(frame: .zero, styleURL: colorScheme == .dark ? builder.dynamicMapURL(for: .dark) : builder.dynamicMapURL(for: .light))
|
||||
|
||||
showUserLocation(in: mapView)
|
||||
mapView.attributionButton.isHidden = true
|
||||
|
||||
mapView.logoViewPosition = .topLeft
|
||||
mapView.attributionButtonPosition = .topLeft
|
||||
mapView.attributionButtonMargins = .init(x: mapView.logoView.frame.maxX + 8, y: mapView.logoView.center.y / 2)
|
||||
return mapView
|
||||
}
|
||||
|
||||
private func showUserLocation(in mapView: MGLMapView) {
|
||||
switch showsUserLocationMode {
|
||||
case .showAndFollow:
|
||||
mapView.showsUserLocation = true
|
||||
switch (showsUserLocationMode, options.annotations) {
|
||||
case (.showAndFollow, _):
|
||||
mapView.userTrackingMode = .follow
|
||||
case .show:
|
||||
case (.show, let annotations) where !annotations.isEmpty:
|
||||
/** in the show mode, if there are annotations, we check the authorizationStatus,
|
||||
if it's not determined, we wont prompt the user with a request for permissions,
|
||||
because he should be able to see the annotations without sharing his location informations
|
||||
**/
|
||||
guard mapView.locationManager.authorizationStatus != .notDetermined else { return }
|
||||
fallthrough
|
||||
case (.show, _):
|
||||
mapView.showsUserLocation = true
|
||||
mapView.userTrackingMode = .none
|
||||
case .hide:
|
||||
mapView.setUserTrackingMode(.none, animated: false, completionHandler: nil)
|
||||
case (.hide, _):
|
||||
mapView.showsUserLocation = false
|
||||
mapView.userTrackingMode = .none
|
||||
mapView.setUserTrackingMode(.none, animated: false, completionHandler: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,11 +119,13 @@ struct MapLibreMapView: UIViewRepresentable {
|
||||
// MARK: - Coordinator
|
||||
|
||||
extension MapLibreMapView {
|
||||
class Coordinator: NSObject, MGLMapViewDelegate, UIGestureRecognizerDelegate {
|
||||
class Coordinator: NSObject, MGLMapViewDelegate {
|
||||
// MARK: - Properties
|
||||
|
||||
var mapLibreView: MapLibreMapView
|
||||
|
||||
private var previousUserLocation: MGLUserLocation?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(_ mapLibreView: MapLibreMapView) {
|
||||
@@ -140,20 +142,30 @@ extension MapLibreMapView {
|
||||
}
|
||||
|
||||
func mapViewDidFailLoadingMap(_ mapView: MGLMapView, withError error: Error) {
|
||||
mapLibreView.error.wrappedValue = .failedLoadingMap
|
||||
mapLibreView.error = .failedLoadingMap
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didUpdate userLocation: MGLUserLocation?) { }
|
||||
func mapView(_ mapView: MGLMapView, didUpdate userLocation: MGLUserLocation?) {
|
||||
guard let userLocation else { return }
|
||||
|
||||
if previousUserLocation == nil, mapLibreView.options.annotations.isEmpty {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
mapView.setCenter(userLocation.coordinate, zoomLevel: self.mapLibreView.options.zoomLevel, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
previousUserLocation = userLocation
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didChangeLocationManagerAuthorization manager: MGLLocationManager) {
|
||||
guard mapView.showsUserLocation else {
|
||||
return
|
||||
}
|
||||
|
||||
switch manager.authorizationStatus {
|
||||
case .denied, .restricted:
|
||||
mapLibreView.error.wrappedValue = .invalidLocationAuthorization
|
||||
default:
|
||||
mapLibreView.isLocationAuthorized = false
|
||||
case .authorizedAlways, .authorizedWhenInUse:
|
||||
mapLibreView.isLocationAuthorized = true
|
||||
case .notDetermined:
|
||||
mapLibreView.isLocationAuthorized = nil
|
||||
@unknown default:
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -171,15 +183,25 @@ extension MapLibreMapView {
|
||||
false
|
||||
}
|
||||
|
||||
// MARK: UIGestureRecognizer
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
gestureRecognizer is UIPanGestureRecognizer
|
||||
}
|
||||
|
||||
@objc
|
||||
func didPan() {
|
||||
mapLibreView.userDidPan?()
|
||||
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera, reason: MGLCameraChangeReason) -> Bool {
|
||||
// we send the userDidPan event only for the reasons that actually will change the map center, and not zoom only / rotations only events.
|
||||
switch reason {
|
||||
case .gesturePan,
|
||||
.gesturePinch,
|
||||
.gestureRotate:
|
||||
mapLibreView.userDidPan?()
|
||||
case .gestureOneFingerZoom,
|
||||
.gestureTilt,
|
||||
.gestureZoomIn,
|
||||
.gestureZoomOut,
|
||||
.programmatic,
|
||||
.resetNorth,
|
||||
.transitionCancelled:
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,3 +216,16 @@ private extension MGLMapView {
|
||||
removeAnnotations(annotations)
|
||||
}
|
||||
}
|
||||
|
||||
private extension MapTilerStyle {
|
||||
init(_ colorScheme: ColorScheme) {
|
||||
switch colorScheme {
|
||||
case .light:
|
||||
self = .light
|
||||
case .dark:
|
||||
self = .dark
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ enum MapTilerStyle {
|
||||
enum MapLibreError: Error {
|
||||
case failedLoadingMap
|
||||
case failedLocatingUser
|
||||
case invalidLocationAuthorization
|
||||
}
|
||||
|
||||
enum MapTilerAttributionPlacement: String {
|
||||
|
||||
@@ -18,12 +18,13 @@ import CoreLocation
|
||||
import Foundation
|
||||
|
||||
enum LocationSharingViewError: Error, Hashable {
|
||||
case failedSharingLocation
|
||||
case missingAuthorization
|
||||
case mapError(MapLibreError)
|
||||
}
|
||||
|
||||
enum StaticLocationScreenViewModelAction {
|
||||
case close
|
||||
case openSystemSettings
|
||||
case sendLocation(GeoURI, isUserLocation: Bool)
|
||||
}
|
||||
|
||||
@@ -33,47 +34,36 @@ enum StaticLocationInteractionMode: Hashable {
|
||||
}
|
||||
|
||||
struct StaticLocationScreenViewState: BindableState {
|
||||
init(interactionMode: StaticLocationInteractionMode, isSharingUserLocation: Bool = false, showsUserLocationMode: ShowUserLocationMode = .hide) {
|
||||
init(interactionMode: StaticLocationInteractionMode) {
|
||||
self.interactionMode = interactionMode
|
||||
self.isSharingUserLocation = isSharingUserLocation
|
||||
self.showsUserLocationMode = showsUserLocationMode
|
||||
|
||||
switch interactionMode {
|
||||
case .picker:
|
||||
bindings = .init()
|
||||
case .viewOnly(let geoURI, _):
|
||||
bindings = .init(mapCenterLocation: .init(latitude: geoURI.latitude, longitude: geoURI.longitude))
|
||||
bindings.showsUserLocationMode = .showAndFollow
|
||||
case .viewOnly:
|
||||
bindings.showsUserLocationMode = .show
|
||||
}
|
||||
}
|
||||
|
||||
let interactionMode: StaticLocationInteractionMode
|
||||
/// Indicates whether the user is sharing his current location
|
||||
var isSharingUserLocation: Bool
|
||||
/// Behavior mode of the current user's location, can be hidden, only shown and shown following the user
|
||||
var showsUserLocationMode: ShowUserLocationMode
|
||||
|
||||
var bindings = StaticLocationScreenBindings()
|
||||
|
||||
var showBottomToolbar: Bool {
|
||||
interactionMode == .picker
|
||||
var isSharingUserLocation: Bool {
|
||||
bindings.isLocationAuthorized == true && bindings.showsUserLocationMode == .showAndFollow
|
||||
}
|
||||
|
||||
var mapAnnotationCoordinate: CLLocationCoordinate2D? {
|
||||
|
||||
var bindings = StaticLocationScreenBindings(showsUserLocationMode: .hide)
|
||||
|
||||
var initialMapCenter: CLLocationCoordinate2D {
|
||||
switch interactionMode {
|
||||
case .picker:
|
||||
return nil
|
||||
// middle point in Europe, to be used if the users location is not yet known
|
||||
return .init(latitude: 49.843, longitude: 9.902056)
|
||||
case .viewOnly(let geoURI, _):
|
||||
return .init(latitude: geoURI.latitude, longitude: geoURI.longitude)
|
||||
}
|
||||
}
|
||||
|
||||
var isLocationPickerMode: Bool {
|
||||
switch interactionMode {
|
||||
case .picker:
|
||||
return true
|
||||
case .viewOnly:
|
||||
return false
|
||||
}
|
||||
interactionMode == .picker
|
||||
}
|
||||
|
||||
var navigationTitle: String {
|
||||
@@ -95,9 +85,13 @@ struct StaticLocationScreenViewState: BindableState {
|
||||
}
|
||||
|
||||
var zoomLevel: Double {
|
||||
15.0
|
||||
}
|
||||
|
||||
var initialZoomLevel: Double {
|
||||
switch interactionMode {
|
||||
case .picker:
|
||||
return 5.0
|
||||
return 2.7
|
||||
case .viewOnly:
|
||||
return 15.0
|
||||
}
|
||||
@@ -115,6 +109,10 @@ struct StaticLocationScreenViewState: BindableState {
|
||||
|
||||
struct StaticLocationScreenBindings {
|
||||
var mapCenterLocation: CLLocationCoordinate2D?
|
||||
|
||||
var showsUserLocationMode: ShowUserLocationMode
|
||||
|
||||
var isLocationAuthorized: Bool?
|
||||
|
||||
/// Information describing the currently displayed alert.
|
||||
var mapError: MapLibreError? {
|
||||
@@ -125,7 +123,7 @@ struct StaticLocationScreenBindings {
|
||||
return nil
|
||||
}
|
||||
set {
|
||||
alertInfo = newValue.map { AlertInfo(id: .mapError($0)) }
|
||||
alertInfo = newValue.map { AlertInfo(locationSharingViewError: .mapError($0)) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,5 +136,33 @@ struct StaticLocationScreenBindings {
|
||||
enum StaticLocationScreenViewAction {
|
||||
case close
|
||||
case selectLocation
|
||||
case centerToUser
|
||||
case userDidPan
|
||||
}
|
||||
|
||||
extension AlertInfo where T == LocationSharingViewError {
|
||||
init(locationSharingViewError error: LocationSharingViewError,
|
||||
primaryButton: AlertButton = AlertButton(title: L10n.actionOk, action: nil),
|
||||
secondaryButton: AlertButton? = nil) {
|
||||
switch error {
|
||||
case .missingAuthorization:
|
||||
self.init(id: error,
|
||||
title: "",
|
||||
message: L10n.errorMissingLocationAuth(InfoPlistReader.main.bundleDisplayName),
|
||||
primaryButton: primaryButton,
|
||||
secondaryButton: secondaryButton)
|
||||
case .mapError(.failedLoadingMap):
|
||||
self.init(id: error,
|
||||
title: "",
|
||||
message: L10n.errorFailedLoadingMap(InfoPlistReader.main.bundleDisplayName),
|
||||
primaryButton: primaryButton,
|
||||
secondaryButton: secondaryButton)
|
||||
case .mapError(.failedLocatingUser):
|
||||
self.init(id: error,
|
||||
title: "",
|
||||
message: L10n.errorFailedLocatingUser(InfoPlistReader.main.bundleDisplayName),
|
||||
primaryButton: primaryButton,
|
||||
secondaryButton: secondaryButton)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,12 @@ final class StaticLocationScreenCoordinator: CoordinatorProtocol {
|
||||
switch action {
|
||||
case .close:
|
||||
actionsSubject.send(.close)
|
||||
case .openSystemSettings:
|
||||
guard let url = URL(string: UIApplication.openSettingsURLString),
|
||||
UIApplication.shared.canOpenURL(url) else {
|
||||
return
|
||||
}
|
||||
UIApplication.shared.open(url)
|
||||
case .sendLocation(let geoURI, let isUserLocation):
|
||||
actionsSubject.send(.selectedLocation(geoURI, isUserLocation: isUserLocation))
|
||||
}
|
||||
|
||||
@@ -38,8 +38,17 @@ class StaticLocationScreenViewModel: StaticLocationScreenViewModelType, StaticLo
|
||||
guard let coordinate = state.bindings.mapCenterLocation else { return }
|
||||
actionsSubject.send(.sendLocation(.init(coordinate: coordinate), isUserLocation: state.isSharingUserLocation))
|
||||
case .userDidPan:
|
||||
state.showsUserLocationMode = .hide
|
||||
state.isSharingUserLocation = false
|
||||
state.bindings.showsUserLocationMode = .show
|
||||
case .centerToUser:
|
||||
switch state.bindings.isLocationAuthorized {
|
||||
case .some(true), .none:
|
||||
state.bindings.showsUserLocationMode = .showAndFollow
|
||||
case .some(false):
|
||||
let action: () -> Void = { [weak self] in self?.actionsSubject.send(.openSystemSettings) }
|
||||
state.bindings.alertInfo = .init(locationSharingViewError: .missingAuthorization,
|
||||
primaryButton: .init(title: L10n.actionNotNow, role: .cancel, action: nil),
|
||||
secondaryButton: .init(title: L10n.commonSettings, action: action))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,17 +44,20 @@ struct StaticLocationScreen: View {
|
||||
ZStack(alignment: .center) {
|
||||
MapLibreMapView(builder: builder,
|
||||
options: mapOptions,
|
||||
showsUserLocationMode: .hide,
|
||||
showsUserLocationMode: $context.showsUserLocationMode,
|
||||
error: $context.mapError,
|
||||
mapCenterCoordinate: $context.mapCenterLocation,
|
||||
userDidPan: {
|
||||
context.send(viewAction: .userDidPan)
|
||||
})
|
||||
isLocationAuthorized: $context.isLocationAuthorized) {
|
||||
context.send(viewAction: .userDidPan)
|
||||
}
|
||||
.ignoresSafeArea(.all, edges: mapSafeAreaEdges)
|
||||
if context.viewState.isLocationPickerMode {
|
||||
LocationMarkerView()
|
||||
}
|
||||
}
|
||||
.ignoresSafeArea(.all, edges: mapSafeAreaEdges)
|
||||
.overlay(alignment: .bottomTrailing) {
|
||||
centerToUserLocationButton
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -72,7 +75,7 @@ struct StaticLocationScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
if context.viewState.showBottomToolbar {
|
||||
if context.viewState.isLocationPickerMode {
|
||||
ToolbarItemGroup(placement: .bottomBar) {
|
||||
selectLocationButton
|
||||
Spacer()
|
||||
@@ -81,19 +84,22 @@ struct StaticLocationScreen: View {
|
||||
}
|
||||
|
||||
private var mapOptions: MapLibreMapView.Options {
|
||||
guard let coordinate = context.viewState.mapAnnotationCoordinate else {
|
||||
return .init(zoomLevel: context.viewState.zoomLevel)
|
||||
var annotations: [LocationAnnotation] = []
|
||||
if context.viewState.isLocationPickerMode == false {
|
||||
let annotation = LocationAnnotation(coordinate: context.viewState.initialMapCenter, anchorPoint: .bottomCenter) {
|
||||
LocationMarkerView()
|
||||
}
|
||||
annotations.append(annotation)
|
||||
}
|
||||
|
||||
return .init(zoomLevel: context.viewState.zoomLevel,
|
||||
mapCenter: coordinate,
|
||||
annotations: [LocationAnnotation(coordinate: coordinate, anchorPoint: .bottomCenter) {
|
||||
LocationMarkerView()
|
||||
}])
|
||||
initialZoomLevel: context.viewState.initialZoomLevel,
|
||||
mapCenter: context.viewState.initialMapCenter,
|
||||
annotations: annotations)
|
||||
}
|
||||
|
||||
private var mapSafeAreaEdges: Edge.Set {
|
||||
context.viewState.showBottomToolbar ? .horizontal : [.horizontal, .bottom]
|
||||
context.viewState.isLocationPickerMode ? .horizontal : [.horizontal, .bottom]
|
||||
}
|
||||
|
||||
@ScaledMetric private var shareMarkerSize: CGFloat = 28
|
||||
@@ -111,6 +117,15 @@ struct StaticLocationScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var centerToUserLocationButton: some View {
|
||||
Button {
|
||||
context.send(viewAction: .centerToUser)
|
||||
} label: {
|
||||
Image(asset: context.viewState.isSharingUserLocation ? Asset.Images.locationPointerFull : Asset.Images.locationPointer)
|
||||
}
|
||||
.padding(16)
|
||||
}
|
||||
|
||||
private var closeButton: some View {
|
||||
Button(L10n.actionCancel) {
|
||||
context.send(viewAction: .close)
|
||||
@@ -127,14 +142,13 @@ struct StaticLocationScreen: View {
|
||||
|
||||
@ViewBuilder
|
||||
private var shareSheet: some View {
|
||||
if let location = context.viewState.mapAnnotationCoordinate {
|
||||
let locationDescription = context.viewState.locationDescription
|
||||
AppActivityView(activityItems: [ShareToMapsAppActivity.MapsAppType.apple.activityURL(for: location, locationDescription: locationDescription)],
|
||||
applicationActivities: ShareToMapsAppActivity.MapsAppType.allCases.map { ShareToMapsAppActivity(type: $0, location: location, locationDescription: locationDescription) })
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
.presentationDetents([.medium, .large])
|
||||
.presentationDragIndicator(.hidden)
|
||||
}
|
||||
let location = context.viewState.initialMapCenter
|
||||
let locationDescription = context.viewState.locationDescription
|
||||
AppActivityView(activityItems: [ShareToMapsAppActivity.MapsAppType.apple.activityURL(for: location, locationDescription: locationDescription)],
|
||||
applicationActivities: ShareToMapsAppActivity.MapsAppType.allCases.map { ShareToMapsAppActivity(type: $0, location: location, locationDescription: locationDescription) })
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
.presentationDetents([.medium, .large])
|
||||
.presentationDragIndicator(.hidden)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
return .none
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity function_body_length
|
||||
private func updateTimelineItems() {
|
||||
var newTimelineItems = [RoomTimelineItemProtocol]()
|
||||
var canBackPaginate = true
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
<false/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera.</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>When you share your location to people, $(APP_DISPLAY_NAME) needs access to show them a map.</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>To take videos with audio and send them as a message $(APP_DISPLAY_NAME) needs access to the microphone.</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
|
||||
@@ -69,6 +69,7 @@ targets:
|
||||
NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera.
|
||||
NSMicrophoneUsageDescription: To take videos with audio and send them as a message $(APP_DISPLAY_NAME) needs access to the microphone.
|
||||
NSPhotoLibraryAddUsageDescription: Allows saving photos and videos to your library.
|
||||
NSLocationWhenInUseUsageDescription: When you share your location to people, $(APP_DISPLAY_NAME) needs access to show them a map.
|
||||
UIBackgroundModes: [
|
||||
fetch
|
||||
]
|
||||
|
||||
@@ -32,13 +32,48 @@ class StaticLocationScreenViewModelTests: XCTestCase {
|
||||
|
||||
override func setUpWithError() throws {
|
||||
let viewModel = StaticLocationScreenViewModel(interactionMode: .picker)
|
||||
viewModel.state.isSharingUserLocation = true
|
||||
viewModel.state.bindings.isLocationAuthorized = true
|
||||
self.viewModel = viewModel
|
||||
}
|
||||
|
||||
func testUserDidPan() async throws {
|
||||
XCTAssertTrue(context.viewState.isSharingUserLocation)
|
||||
XCTAssertEqual(context.showsUserLocationMode, .showAndFollow)
|
||||
context.send(viewAction: .userDidPan)
|
||||
XCTAssertFalse(context.viewState.isSharingUserLocation)
|
||||
XCTAssertEqual(context.showsUserLocationMode, .show)
|
||||
}
|
||||
|
||||
func testCenterOnUser() async throws {
|
||||
XCTAssertTrue(context.viewState.isSharingUserLocation)
|
||||
context.showsUserLocationMode = .show
|
||||
XCTAssertFalse(context.viewState.isSharingUserLocation)
|
||||
context.send(viewAction: .centerToUser)
|
||||
XCTAssertTrue(context.viewState.isSharingUserLocation)
|
||||
XCTAssertEqual(context.showsUserLocationMode, .showAndFollow)
|
||||
}
|
||||
|
||||
func testCenterOnUserWithoutAuth() async throws {
|
||||
context.showsUserLocationMode = .hide
|
||||
context.isLocationAuthorized = nil
|
||||
context.send(viewAction: .centerToUser)
|
||||
XCTAssertEqual(context.showsUserLocationMode, .showAndFollow)
|
||||
}
|
||||
|
||||
func testCenterOnUserWithDeniedAuth() async throws {
|
||||
context.isLocationAuthorized = false
|
||||
context.showsUserLocationMode = .hide
|
||||
context.send(viewAction: .centerToUser)
|
||||
XCTAssertNotEqual(context.showsUserLocationMode, .showAndFollow)
|
||||
XCTAssertNotNil(context.alertInfo)
|
||||
}
|
||||
|
||||
func testErrorMapping() async throws {
|
||||
let mapError = AlertInfo(locationSharingViewError: .mapError(.failedLoadingMap))
|
||||
XCTAssertEqual(mapError.message, L10n.errorFailedLoadingMap(InfoPlistReader.main.bundleDisplayName))
|
||||
let locationError = AlertInfo(locationSharingViewError: .mapError(.failedLocatingUser))
|
||||
XCTAssertEqual(locationError.message, L10n.errorFailedLocatingUser(InfoPlistReader.main.bundleDisplayName))
|
||||
let authorizationError = AlertInfo(locationSharingViewError: .missingAuthorization)
|
||||
XCTAssertEqual(authorizationError.message, L10n.errorMissingLocationAuth(InfoPlistReader.main.bundleDisplayName))
|
||||
}
|
||||
}
|
||||
|
||||
1
changelog.d/1272.feature
Normal file
1
changelog.d/1272.feature
Normal file
@@ -0,0 +1 @@
|
||||
Send current user location
|
||||
Reference in New Issue
Block a user