Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 85c9f333ce | |||
| 217cbfd4e3 | |||
| 5d8de1fb36 | |||
| f23bb78ceb | |||
| 0d91954614 | |||
| 49f5fa91fe | |||
| 68e560768b | |||
| 3e9c319b50 | |||
| d35e0e1b4a | |||
| 6ede137ef7 | |||
| c94195d48e | |||
| 28919d7b72 | |||
| a239534b91 | |||
| 226342f36c | |||
| ca6afbec5f | |||
| 465d3e8013 | |||
| a7e88b43f5 | |||
| 57ef877846 | |||
| c44d97b9fb | |||
| fd4ed7f66f | |||
| ef5db97854 | |||
| ce0e17a0c5 | |||
| 2a46f1d2d6 | |||
| 93871f0358 | |||
| 3e8fe0680d | |||
| 6be5f72360 | |||
| ccd1b9de59 | |||
| 5737eb5b02 | |||
| c549bb6ea5 | |||
| ff80905033 |
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## Versione 5.9
|
||||
- Aggiunta barra laterale in lista sismi
|
||||
|
||||
## Versione 5.8.1
|
||||
- Corrette traduzioni errate (causavano crash)
|
||||
- Aggiunto ordinamento in sottoscrizioni utente (prima Top10k)
|
||||
|
||||
## Versione 5.8
|
||||
- Modifica algoritmo filtro lista (issue #70)
|
||||
- Modifica impostazioni "Notifiche da reti sismiche" (issue #66)
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
656E02162C1C4DF2008D0E92 /* EQNBaseContainerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 656E02152C1C4DF2008D0E92 /* EQNBaseContainerTableViewCell.swift */; };
|
||||
656EB9362A15FD16009DADF3 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 656EB9382A15FD16009DADF3 /* Localizable.stringsdict */; };
|
||||
656EB9412A16288A009DADF3 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 656EB9382A15FD16009DADF3 /* Localizable.stringsdict */; };
|
||||
657747FD2D4D12A200213830 /* SeismicNetworkData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657747FC2D4D12A200213830 /* SeismicNetworkData.swift */; };
|
||||
657747FF2D4D2BA200213830 /* SeismicNetworkScrollIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */; };
|
||||
6586971125F44C26009C0182 /* EQNBlurredCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */; };
|
||||
658BAB7B25FE67930015C454 /* EQNBaseMapRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */; };
|
||||
658BC0292859A456009EECAA /* RealtimeAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */; };
|
||||
@@ -338,6 +340,8 @@
|
||||
656EB93E2A15FD1E009DADF3 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
656EB93F2A15FD1F009DADF3 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = es; path = es.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
656EB9402A15FD1F009DADF3 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "tr-TR"; path = "tr-TR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
657747FC2D4D12A200213830 /* SeismicNetworkData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkData.swift; sourceTree = "<group>"; };
|
||||
657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkScrollIndicatorView.swift; sourceTree = "<group>"; };
|
||||
6586971025F44C26009C0182 /* EQNBlurredCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBlurredCloseButton.swift; sourceTree = "<group>"; };
|
||||
658BAB7A25FE67930015C454 /* EQNBaseMapRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBaseMapRepresentable.swift; sourceTree = "<group>"; };
|
||||
658BC0282859A456009EECAA /* RealtimeAlertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeAlertViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -912,9 +916,11 @@
|
||||
DC141968250E769B0059E060 /* Seismic Networks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */,
|
||||
DC28142E2519C21400C1AFF7 /* Cells */,
|
||||
65F0857E2609288E0002615C /* Filters */,
|
||||
6562C80625FFA6B100C85273 /* SeismicNetworkViewModel.swift */,
|
||||
657747FC2D4D12A200213830 /* SeismicNetworkData.swift */,
|
||||
657747FE2D4D2BA100213830 /* SeismicNetworkScrollIndicatorView.swift */,
|
||||
DC2814372519C56100C1AFF7 /* SeismicNetworksViewController.swift */,
|
||||
DCC76BD7251F56050005C4DC /* SeismicCardSettingsViewController.swift */,
|
||||
65DBFB4A25E29DD60041CBA6 /* SeismicNetworksMapDetailViewController.swift */,
|
||||
@@ -1290,8 +1296,9 @@
|
||||
8CBD3DBA2149B9AD0070C963 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastSwiftUpdateCheck = 1410;
|
||||
LastUpgradeCheck = 1410;
|
||||
LastUpgradeCheck = 1620;
|
||||
ORGANIZATIONNAME = "Earthquake Network";
|
||||
TargetAttributes = {
|
||||
65FFDC91292F672B00EA821B = {
|
||||
@@ -1559,6 +1566,7 @@
|
||||
DC03BEAB250BC0A60084769B /* EQNRoundedButton.swift in Sources */,
|
||||
65AD23CE261B03D400E3B57C /* SubscriptionsDescriptionTableViewCell.swift in Sources */,
|
||||
DCD4571C24F6CF0D00B58304 /* EQNGenericValue.swift in Sources */,
|
||||
657747FD2D4D12A200213830 /* SeismicNetworkData.swift in Sources */,
|
||||
8C4E343F215012FA008B0D2A /* EQNManager.m in Sources */,
|
||||
DCAA913F24F68A1D00145A3D /* SettingMultivaluesTableViewCell.swift in Sources */,
|
||||
DCF9E14F24F6EA07002B6B1D /* EQNSeismicNetwork.swift in Sources */,
|
||||
@@ -1596,6 +1604,7 @@
|
||||
8CF6604F214C0E58009F4314 /* EQNCalibrazione.m in Sources */,
|
||||
65355FFF25F38D3300BB57D2 /* SegnalazioniMapViewController.swift in Sources */,
|
||||
DCBB84F0252CFC4600F12633 /* AlertsNoLocationTableViewCell.swift in Sources */,
|
||||
657747FF2D4D2BA200213830 /* SeismicNetworkScrollIndicatorView.swift in Sources */,
|
||||
651901B925F5358700CAFF20 /* EQNMapAnnotationSeismic.swift in Sources */,
|
||||
DC99A50324E66E270071BC9F /* EQNCommandProtocol.swift in Sources */,
|
||||
DCF10DC624D2B8C7009F34C3 /* EQNPurchaseUtility.swift in Sources */,
|
||||
@@ -1773,7 +1782,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 135;
|
||||
CURRENT_PROJECT_VERSION = 142;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = WJA4MR4CPC;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
@@ -1790,7 +1799,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.8;
|
||||
MARKETING_VERSION = 5.9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
||||
@@ -1815,7 +1824,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 135;
|
||||
CURRENT_PROJECT_VERSION = 142;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = WJA4MR4CPC;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1828,7 +1837,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.8;
|
||||
MARKETING_VERSION = 5.9.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationservice;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1964,16 +1973,16 @@
|
||||
8CBD3DDC2149B9AD0070C963 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 135;
|
||||
CURRENT_PROJECT_VERSION = 142;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
ENABLE_MODULE_VERIFIER = YES;
|
||||
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
||||
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
@@ -1981,7 +1990,8 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.8;
|
||||
MARKETING_VERSION = 5.9.0;
|
||||
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -2051,15 +2061,15 @@
|
||||
8CBD3DDD2149B9AD0070C963 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Earthquake Network/Earthquake Network.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 135;
|
||||
CURRENT_PROJECT_VERSION = 142;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
ENABLE_MODULE_VERIFIER = YES;
|
||||
GCC_PREFIX_HEADER = "Earthquake Network/Earthquake Network-Prefix.pch";
|
||||
INFOPLIST_FILE = "Earthquake Network/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
@@ -2067,7 +2077,8 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.8;
|
||||
MARKETING_VERSION = 5.9.0;
|
||||
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -2140,7 +2151,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 135;
|
||||
CURRENT_PROJECT_VERSION = 142;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@@ -2155,7 +2166,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.8;
|
||||
MARKETING_VERSION = 5.9.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - Development";
|
||||
@@ -2174,7 +2185,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = EQNNotificationContent/EQNNotificationContent.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 135;
|
||||
CURRENT_PROJECT_VERSION = 142;
|
||||
DEVELOPMENT_TEAM = WJA4MR4CPC;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"ADS_ENABLED=0",
|
||||
@@ -2187,7 +2198,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.8;
|
||||
MARKETING_VERSION = 5.9.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.finazzi.distquake.notificationcontent;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "EQNetwork Extension Content - AppStore";
|
||||
@@ -2242,7 +2253,7 @@
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
6552C13629262119008E723C /* XCRemoteSwiftPackageReference "Shogun" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/andreabusi-it/Shogun";
|
||||
repositoryURL = "https://github.com/andreabusi-it/Shogun.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 1.0.0;
|
||||
@@ -2269,7 +2280,7 @@
|
||||
repositoryURL = "https://github.com/googleads/swift-package-manager-google-mobile-ads.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 11.3.0;
|
||||
minimumVersion = 12.0.0;
|
||||
};
|
||||
};
|
||||
65B16E282BDFB39B0020527E /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */ = {
|
||||
@@ -2277,7 +2288,7 @@
|
||||
repositoryURL = "https://github.com/facebook/facebook-ios-sdk";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 14.1.0;
|
||||
minimumVersion = 18.0.0;
|
||||
};
|
||||
};
|
||||
65E6AC6C2C2DB3B60073F8FE /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
|
||||
@@ -2285,7 +2296,7 @@
|
||||
repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 10.28.1;
|
||||
minimumVersion = 11.1.0;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
+19
-19
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"originHash" : "c29b9b16ee6b4d1a6fec2debc59749097860256c8cbb2addc2abc08d3adba59d",
|
||||
"originHash" : "898a30d298491e1ce821191ebfa2e7d28e7c9ea4c119cbfdfb1b245bc94ac6c3",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "abseil-cpp-binary",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/google/abseil-cpp-binary.git",
|
||||
"state" : {
|
||||
"revision" : "748c7837511d0e6a507737353af268484e1745e2",
|
||||
"version" : "1.2024011601.1"
|
||||
"revision" : "194a6706acbd25e4ef639bcaddea16e8758a3e27",
|
||||
"version" : "1.2024011602.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -15,8 +15,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/google/app-check.git",
|
||||
"state" : {
|
||||
"revision" : "3b62f154d00019ae29a71e9738800bb6f18b236d",
|
||||
"version" : "10.19.2"
|
||||
"revision" : "61b85103a1aeed8218f17c794687781505fbbef5",
|
||||
"version" : "11.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -33,8 +33,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/facebook/facebook-ios-sdk",
|
||||
"state" : {
|
||||
"revision" : "c19607d535864533523d1f437c84035e5fb101cf",
|
||||
"version" : "14.1.0"
|
||||
"revision" : "b28dde427715b45a26ebebf697929f4a81b15e04",
|
||||
"version" : "18.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -42,8 +42,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/firebase/firebase-ios-sdk.git",
|
||||
"state" : {
|
||||
"revision" : "e57841b296d04370ea23580f908881b0ccab17b9",
|
||||
"version" : "10.28.1"
|
||||
"revision" : "075679d6b25b28f4cb167f1d7769b58fb556fb30",
|
||||
"version" : "11.8.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -51,8 +51,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/google/GoogleAppMeasurement.git",
|
||||
"state" : {
|
||||
"revision" : "fe727587518729046fc1465625b9afd80b5ab361",
|
||||
"version" : "10.28.0"
|
||||
"revision" : "be0881ff728eca210ccb628092af400c086abda3",
|
||||
"version" : "11.7.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -60,8 +60,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/google/GoogleDataTransport.git",
|
||||
"state" : {
|
||||
"revision" : "a637d318ae7ae246b02d7305121275bc75ed5565",
|
||||
"version" : "9.4.0"
|
||||
"revision" : "617af071af9aa1d6a091d59a202910ac482128f9",
|
||||
"version" : "10.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -69,8 +69,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/google/GoogleUtilities.git",
|
||||
"state" : {
|
||||
"revision" : "57a1d307f42df690fdef2637f3e5b776da02aad6",
|
||||
"version" : "7.13.3"
|
||||
"revision" : "53156c7ec267db846e6b64c9f4c4e31ba4cf75eb",
|
||||
"version" : "8.0.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -78,8 +78,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/google/grpc-binary.git",
|
||||
"state" : {
|
||||
"revision" : "e9fad491d0673bdda7063a0341fb6b47a30c5359",
|
||||
"version" : "1.62.2"
|
||||
"revision" : "f56d8fc3162de9a498377c7b6cea43431f4f5083",
|
||||
"version" : "1.65.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -150,8 +150,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/googleads/swift-package-manager-google-mobile-ads.git",
|
||||
"state" : {
|
||||
"revision" : "9ab66e38f5f0c2d02f2b024b1babd880130f19bf",
|
||||
"version" : "11.3.0"
|
||||
"revision" : "aa24c7dc03bca62c42747314dc8537f15587b50d",
|
||||
"version" : "12.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1410"
|
||||
LastUpgradeVersion = "1620"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1410"
|
||||
LastUpgradeVersion = "1620"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
@@ -15,7 +15,7 @@
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8C4B0B7921CACE3F00AED489"
|
||||
BlueprintIdentifier = "65FFDC91292F672B00EA821B"
|
||||
BuildableName = "EQNNotificationService.appex"
|
||||
BlueprintName = "EQNNotificationService"
|
||||
ReferencedContainer = "container:Earthquake Network.xcodeproj">
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1410"
|
||||
LastUpgradeVersion = "1620"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -212,14 +212,14 @@
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
|
||||
if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
|
||||
[FBSDKSettings.sharedSettings setAdvertiserTrackingEnabled:YES];
|
||||
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
|
||||
} else {
|
||||
[FBSDKSettings.sharedSettings setAdvertiserTrackingEnabled:NO];
|
||||
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = NO;
|
||||
}
|
||||
}];
|
||||
});
|
||||
} else {
|
||||
[FBSDKSettings.sharedSettings setAdvertiserTrackingEnabled:YES];
|
||||
FBSDKSettings.sharedSettings.isAdvertiserTrackingEnabled = YES;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@
|
||||
- (void)configureFacebookSDKWithApplication:(UIApplication *)application andOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
[FBSDKApplicationDelegate.sharedInstance application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
[FBSDKSettings.sharedSettings setAdvertiserIDCollectionEnabled:YES];
|
||||
FBSDKSettings.sharedSettings.isAdvertiserIDCollectionEnabled = YES;
|
||||
}
|
||||
|
||||
#pragma mark - FIRMessagingDelegate
|
||||
|
||||
@@ -37,6 +37,7 @@ extension UserDefaults {
|
||||
static let UserReportCodeStatus = "CODE_MESSAGE_EQN"
|
||||
|
||||
// Proprietà e preferenze dell'utente
|
||||
static let FirstAppStartExecuted = "EQNUserDefaultFirstAppStartExecuted"
|
||||
/// Ultima posizione conosciuta dell'utente
|
||||
static let UserDataLastLocation = "EQNLast_Location"
|
||||
/// Token Firebase dell'utente corrente
|
||||
@@ -60,6 +61,7 @@ extension UserDefaults {
|
||||
static let AppMigrationV5_3 = "EQNUserDefaultMigrationV5_3"
|
||||
static let AppMigrationV5_4 = "EQNUserDefaultMigrationV5_4"
|
||||
static let AppMigrationV5_8 = "EQNUserDefaultMigrationV5_8"
|
||||
static let AppMigrationV5_8_2 = "EQNUserDefaultMigrationV5_8_2"
|
||||
|
||||
static let SettingsSeismicNetworkNotificationMigrationV5_8 = "EQNUserDefaultSettingsSeismicNetworkNotificationMigrationV5_8"
|
||||
static let SettingsUserReportNotificationMigrationV5_8 = "EQNUserDefaultSettingsUserReportNotificationMigrationV5_8"
|
||||
|
||||
@@ -107,11 +107,22 @@ class SubscriptionsViewController: UITableViewController {
|
||||
|
||||
let products = storeProducts.compactMap { EQNInAppProducts.from(product: $0) }
|
||||
|
||||
let purchased = products.filter { (product) -> Bool in
|
||||
let isPurchased = EQNInAppProducts.store.isProductPurchased(product.productIdentifier)
|
||||
let isSubscription = product.isSubscription
|
||||
return isPurchased && isSubscription
|
||||
}
|
||||
let purchased = products
|
||||
.filter { (product) -> Bool in
|
||||
// filter for subscriptions
|
||||
let isPurchased = EQNInAppProducts.store.isProductPurchased(product.productIdentifier)
|
||||
let isSubscription = product.isSubscription
|
||||
return isPurchased && isSubscription
|
||||
}.sorted { lProduct, rProduct in
|
||||
// if user has more than one subscriptions,
|
||||
// show first the Top10k
|
||||
let lIs10k = lProduct.isTop100k
|
||||
let rIs10k = rProduct.isTop100k
|
||||
if lIs10k {
|
||||
return lIs10k
|
||||
}
|
||||
return rIs10k
|
||||
}
|
||||
self.productSubscribed = purchased.first
|
||||
self.products = products.sorted(by: { $0.productIdentifier > $1.productIdentifier })
|
||||
self.tableView.reloadData()
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ class SeismicNetworkAdvertiseTableViewCell: UITableViewCell {
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var bannerView: GADNativeAdView = {
|
||||
private lazy var bannerView: NativeAdView = {
|
||||
let view = GADTMediumTemplateView()
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
return view
|
||||
@@ -71,7 +71,7 @@ class SeismicNetworkAdvertiseTableViewCell: UITableViewCell {
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func loadNativeAd(_ nativeAd: GADNativeAd) {
|
||||
func loadNativeAd(_ nativeAd: NativeAd) {
|
||||
bannerView.nativeAd = nativeAd
|
||||
}
|
||||
}
|
||||
|
||||
+4
-64
@@ -23,9 +23,7 @@ protocol SeismicNetworkTableViewCellDelegate: AnyObject {
|
||||
class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
|
||||
static let Identifier = "SeismicNetworkTableViewCell"
|
||||
|
||||
typealias MagnitudeColors = (textColor: UIColor, startColor: UIColor, endColor: UIColor)
|
||||
|
||||
|
||||
/// Available informations to display inside the cell
|
||||
enum InformationType: Int {
|
||||
case preliminary
|
||||
@@ -58,8 +56,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
private(set) var displayType = DisplayType.normal
|
||||
private var informationTypes = [InformationType]()
|
||||
private var isPushSelected = false
|
||||
|
||||
private var colors: MagnitudeColors?
|
||||
|
||||
// MARK: - UI Components
|
||||
|
||||
@@ -398,17 +394,13 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
|
||||
let viewModel = SeismicNetworkViewModel(seismic: seismic)
|
||||
|
||||
if let colors = colors {
|
||||
gradientView.image = .gradient(from: colors.startColor, to: colors.endColor, with: .init(origin: .zero, size: .init(width: 500, height: 1)))
|
||||
} else {
|
||||
gradientView.image = nil
|
||||
}
|
||||
|
||||
gradientView.image = .gradient(from: viewModel.colors.startColor, to: viewModel.colors.endColor, with: .init(origin: .zero, size: .init(width: 500, height: 1)))
|
||||
|
||||
// update seismic data
|
||||
placeLabel.text = viewModel.place
|
||||
placeLabel.textColor = isPushSelected ? AppTheme.Colors.pureBlue : AppTheme.shared.cardTextColor
|
||||
networkLabel.text = String(format: NSLocalizedString("official_provider", comment: ""), viewModel.network)
|
||||
magnitudeLabel.textColor = colors?.textColor
|
||||
magnitudeLabel.textColor = viewModel.colors.textColor
|
||||
magnitudeLabel.text = viewModel.magnitude
|
||||
depthLabel.text = viewModel.depth
|
||||
timeLabel.text = "🕗 \(viewModel.time)"
|
||||
@@ -461,7 +453,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
isPushSelected: Bool
|
||||
) {
|
||||
self.seismic = seismic
|
||||
self.colors = calculateColors(for: seismic.magnitude.doubleValue)
|
||||
self.displayType = type
|
||||
self.informationTypes = informations
|
||||
self.isPushSelected = isPushSelected
|
||||
@@ -541,55 +532,4 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
}
|
||||
return zoom
|
||||
}
|
||||
|
||||
/// Calculate colors to use for text and background of the cell
|
||||
private func calculateColors(for magnitude: Double) -> MagnitudeColors {
|
||||
var textColor = UIColor.black
|
||||
|
||||
var r = 0, g = 0, b = 0
|
||||
if (magnitude < 2.0) {
|
||||
let fraction: Double = 1 - (magnitude - 0.0) / (2.0 - 0.0)
|
||||
r = Int(round(200.0 + (255.0 - 200.0) * fraction))
|
||||
g = Int(round(226.0 + (255.0 - 226.0) * fraction))
|
||||
b = Int(round(196.0 + (255.0 - 196.0) * fraction))
|
||||
textColor = UIColor(red: 12.0 / 255.0, green: 115.0 / 255.0, blue: 160.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 2.0 && magnitude < 3.5) {
|
||||
let fraction: Double = 1 - (magnitude - 2) / (3.5 - 2)
|
||||
r = Int(round(136.0 + (200.0 - 136.0) * fraction))
|
||||
g = Int(round(175.0 + (226.0 - 175.0) * fraction))
|
||||
b = Int(round(131.0 + (196.0 - 131.0) * fraction))
|
||||
textColor = UIColor(red: 12.0 / 255.0, green: 160.0 / 255.0, blue: 35.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 3.5 && magnitude < 4.5) {
|
||||
let fraction: Double = 1 - (magnitude - 3.5) / (4.5 - 3.5)
|
||||
r = 252
|
||||
g = Int(round(233.0 + (253.0 - 233.0) * fraction))
|
||||
b = Int(round(179.0 + (209.0 - 179.0) * fraction))
|
||||
textColor = UIColor(red: 244.0 / 255.0, green: 195.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 4.5 && magnitude < 5.5) {
|
||||
let fraction: Double = 1 - (magnitude - 4.5) / (5.5 - 4.5)
|
||||
r = 252
|
||||
g = Int(round(159.0 + (197.0 - 159.0) * fraction))
|
||||
b = Int(round(161.0 + (197.0 - 161.0) * fraction))
|
||||
textColor = UIColor(red: 255.0 / 255.0, green: 0.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 5.5) {
|
||||
let fraction: Double = 1 - (magnitude - 5.5) / (10 - 5.5)
|
||||
r = Int(round(190.0 + (254.0 - 190.0) * fraction))
|
||||
g = Int(round(124.0 + (219.0 - 124.0) * fraction))
|
||||
b = 255
|
||||
textColor = UIColor(red: 183.0 / 255.0, green: 60.0 / 255.0, blue: 252.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
|
||||
let r2 = min(r + 30, 255)
|
||||
let g2 = min(g + 30, 255)
|
||||
let b2 = min(b + 30, 255)
|
||||
|
||||
let startColor = UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1.0)
|
||||
let endColor = UIColor(red: CGFloat(r2) / 255.0, green: CGFloat(g2) / 255.0, blue: CGFloat(b2) / 255.0, alpha: 1.0)
|
||||
|
||||
return (textColor: textColor, startColor: startColor, endColor: endColor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// SeismicNetworkData.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 31/01/25.
|
||||
// Copyright © 2025 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// SeismicNetworkScrollIndicatorView.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 31/01/25.
|
||||
// Copyright © 2025 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import CoreGraphics
|
||||
|
||||
|
||||
class SeismicNetworkScrollIndicatorView: UIView {
|
||||
|
||||
private static let HighlightColor: UIColor = .red
|
||||
|
||||
var seismics: [SeismicNetworkViewModel] = [] {
|
||||
didSet {
|
||||
setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
var highlighted: SeismicNetworkViewModel? {
|
||||
didSet {
|
||||
setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
private var numberOfRectangles: Int {
|
||||
seismics.count
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
override func draw(_ rect: CGRect) {
|
||||
guard numberOfRectangles > 0 else { return }
|
||||
|
||||
let context = UIGraphicsGetCurrentContext()
|
||||
let rectStandardWidth = rect.width
|
||||
let rectStandardHeight = rect.height / CGFloat(numberOfRectangles)
|
||||
let rectHighlightedMinHeight: CGFloat = 4
|
||||
|
||||
let smallRectangles = rectStandardHeight < 10
|
||||
let highlightIndex = seismics.firstIndex(where: { $0 == highlighted }) ?? 100_000
|
||||
|
||||
|
||||
seismics.enumerated().forEach { index, seismic in
|
||||
// Disegniamo un rettangolo per ogni sisma, quello evidenziato deve avere un contorno rosso.
|
||||
// Ci sono situazioni in cui ci sono molti sismi da mostrare, quindi in quel caso facciamo alcune modifiche:
|
||||
// - usiamo un'altezza minma per il sisma evidenziato
|
||||
// - per il sisma evidenziato, anche il contenuto è rosso (e non solo il bordo)
|
||||
// - negli altri sismi, non mostriamo il bordo
|
||||
|
||||
if highlightIndex == index {
|
||||
// Stiamo disegnando il sisma evidenziato.
|
||||
// Valutiamo se utilizzare l'altezza minima.
|
||||
let rectHeight = smallRectangles ? rectHighlightedMinHeight : rectStandardHeight
|
||||
let yPosition = CGFloat(index) * rectStandardHeight
|
||||
let rectangle = CGRect(x: 0, y: yPosition, width: rectStandardWidth, height: rectHeight)
|
||||
|
||||
let fillColor = smallRectangles ? Self.HighlightColor : seismic.colors.textColor.withAlphaComponent(0.3)
|
||||
context?.setFillColor(fillColor.cgColor)
|
||||
context?.fill(rectangle)
|
||||
|
||||
if !smallRectangles {
|
||||
// disegniamo il bordo solo se i rettangoli non sono piccoli
|
||||
let borderWidth: CGFloat = 2.0
|
||||
context?.setStrokeColor(Self.HighlightColor.cgColor)
|
||||
context?.setLineWidth(borderWidth) // Spessore del bordo
|
||||
context?.stroke(rectangle.insetBy(dx: borderWidth / 2, dy: borderWidth / 2)) // Evita che il bordo venga tagliato
|
||||
}
|
||||
} else {
|
||||
// Stiamo disegnando i sismi non evidenziati, utilizziamo sempre l'altezza predefinita
|
||||
// Dobbiamo eventualmente calcolare un offset aggiuntivo,
|
||||
// perchè il sisma evidenziato ha un'altezza maggiore (se i rettangoli sono piccoli)
|
||||
let rectHeight = rectStandardHeight
|
||||
let offset: CGFloat = (index > highlightIndex && smallRectangles) ? rectHighlightedMinHeight : 0
|
||||
let yPosition = CGFloat(index) * rectHeight + offset
|
||||
let rectangle = CGRect(x: 0, y: yPosition, width: rectStandardWidth, height: rectHeight)
|
||||
|
||||
let fillColor = seismic.colors.textColor.withAlphaComponent(0.3)
|
||||
context?.setFillColor(fillColor.cgColor)
|
||||
context?.fill(rectangle)
|
||||
|
||||
if !smallRectangles {
|
||||
// altrimenti un bordo grigio
|
||||
let borderWidth: CGFloat = 0.5
|
||||
context?.setStrokeColor(AppTheme.Colors.gray.cgColor)
|
||||
context?.setLineWidth(borderWidth) // Spessore del bordo
|
||||
context?.stroke(rectangle) // Evita che il bordo venga tagliato
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,13 @@ import Foundation
|
||||
|
||||
struct SeismicNetworkViewModel {
|
||||
|
||||
struct MagnitudeColors {
|
||||
let textColor: UIColor
|
||||
let startColor: UIColor
|
||||
let endColor: UIColor
|
||||
}
|
||||
|
||||
private let seismic: EQNSisma
|
||||
let place: String
|
||||
let network: String
|
||||
let isPreliminary: Bool
|
||||
@@ -23,10 +30,12 @@ struct SeismicNetworkViewModel {
|
||||
let population: String
|
||||
let smartphones: String
|
||||
let users: String
|
||||
let colors: MagnitudeColors
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
init(seismic: EQNSisma) {
|
||||
self.seismic = seismic
|
||||
self.place = seismic.place
|
||||
self.network = seismic.provider
|
||||
self.rawMagnitude = seismic.magnitude.doubleValue
|
||||
@@ -71,6 +80,8 @@ struct SeismicNetworkViewModel {
|
||||
} else {
|
||||
self.users = ""
|
||||
}
|
||||
|
||||
self.colors = Self.calculateColors(for: seismic.magnitude.doubleValue)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -90,4 +101,62 @@ struct SeismicNetworkViewModel {
|
||||
}
|
||||
return populationString
|
||||
}
|
||||
|
||||
/// Calculate colors to use for text and background of the cell
|
||||
private static func calculateColors(for magnitude: Double) -> MagnitudeColors {
|
||||
var textColor = UIColor.black
|
||||
|
||||
var r = 0, g = 0, b = 0
|
||||
if (magnitude < 2.0) {
|
||||
let fraction: Double = 1 - (magnitude - 0.0) / (2.0 - 0.0)
|
||||
r = Int(round(200.0 + (255.0 - 200.0) * fraction))
|
||||
g = Int(round(226.0 + (255.0 - 226.0) * fraction))
|
||||
b = Int(round(196.0 + (255.0 - 196.0) * fraction))
|
||||
textColor = UIColor(red: 12.0 / 255.0, green: 115.0 / 255.0, blue: 160.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 2.0 && magnitude < 3.5) {
|
||||
let fraction: Double = 1 - (magnitude - 2) / (3.5 - 2)
|
||||
r = Int(round(136.0 + (200.0 - 136.0) * fraction))
|
||||
g = Int(round(175.0 + (226.0 - 175.0) * fraction))
|
||||
b = Int(round(131.0 + (196.0 - 131.0) * fraction))
|
||||
textColor = UIColor(red: 12.0 / 255.0, green: 160.0 / 255.0, blue: 35.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 3.5 && magnitude < 4.5) {
|
||||
let fraction: Double = 1 - (magnitude - 3.5) / (4.5 - 3.5)
|
||||
r = 252
|
||||
g = Int(round(233.0 + (253.0 - 233.0) * fraction))
|
||||
b = Int(round(179.0 + (209.0 - 179.0) * fraction))
|
||||
textColor = UIColor(red: 244.0 / 255.0, green: 195.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 4.5 && magnitude < 5.5) {
|
||||
let fraction: Double = 1 - (magnitude - 4.5) / (5.5 - 4.5)
|
||||
r = 252
|
||||
g = Int(round(159.0 + (197.0 - 159.0) * fraction))
|
||||
b = Int(round(161.0 + (197.0 - 161.0) * fraction))
|
||||
textColor = UIColor(red: 255.0 / 255.0, green: 0.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 5.5) {
|
||||
let fraction: Double = 1 - (magnitude - 5.5) / (10 - 5.5)
|
||||
r = Int(round(190.0 + (254.0 - 190.0) * fraction))
|
||||
g = Int(round(124.0 + (219.0 - 124.0) * fraction))
|
||||
b = 255
|
||||
textColor = UIColor(red: 183.0 / 255.0, green: 60.0 / 255.0, blue: 252.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
|
||||
let r2 = min(r + 30, 255)
|
||||
let g2 = min(g + 30, 255)
|
||||
let b2 = min(b + 30, 255)
|
||||
|
||||
let startColor = UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1.0)
|
||||
let endColor = UIColor(red: CGFloat(r2) / 255.0, green: CGFloat(g2) / 255.0, blue: CGFloat(b2) / 255.0, alpha: 1.0)
|
||||
|
||||
return .init(textColor: textColor, startColor: startColor, endColor: endColor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SeismicNetworkViewModel: Equatable {
|
||||
static func == (lhs: SeismicNetworkViewModel, rhs: SeismicNetworkViewModel) -> Bool {
|
||||
return lhs.seismic == rhs.seismic
|
||||
}
|
||||
}
|
||||
|
||||
+72
-12
@@ -15,7 +15,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
|
||||
private enum CellType {
|
||||
case seismic(EQNSisma)
|
||||
case advertise(GADNativeAd)
|
||||
case advertise(NativeAd)
|
||||
}
|
||||
|
||||
private static let SegueIdentifierFilters = "ShowFilters"
|
||||
@@ -24,8 +24,8 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
// MARK: - Internal
|
||||
|
||||
/// The ad loader
|
||||
private lazy var adLoader: GADAdLoader = {
|
||||
let adLoader = GADAdLoader(
|
||||
private lazy var adLoader: AdLoader = {
|
||||
let adLoader = AdLoader(
|
||||
adUnitID: EQNAdMobAppIdNativeBanner, rootViewController: self,
|
||||
adTypes: [.native], options: nil)
|
||||
adLoader.delegate = self
|
||||
@@ -34,6 +34,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
|
||||
/// Cells to display (must be seismics or ad banners)
|
||||
private var rows = [CellType]()
|
||||
private var seismicViewModels = [SeismicNetworkViewModel]()
|
||||
/// Informations to display on a single cell
|
||||
private var informations = [SeismicNetworkTableViewCell.InformationType]()
|
||||
/// Index path of row with map expanded
|
||||
@@ -47,6 +48,8 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
private var scrollToOpenedSeismic = false
|
||||
/// Current displayed controller with map
|
||||
private weak var currentMapController: SeismicNetworksMapDetailViewController?
|
||||
/// Keep track of the current cell at the center
|
||||
private var currentCenteredIndexPath: IndexPath?
|
||||
|
||||
// MARK: - UI
|
||||
|
||||
@@ -59,6 +62,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = self
|
||||
tableView.showsVerticalScrollIndicator = false
|
||||
return tableView
|
||||
}()
|
||||
|
||||
@@ -85,6 +89,14 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
label.textAlignment = .center
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var scrollIndicatorView: SeismicNetworkScrollIndicatorView = {
|
||||
let view = SeismicNetworkScrollIndicatorView(frame: .zero)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.backgroundColor = .clear
|
||||
view.layer.borderColor = AppTheme.Colors.gray.cgColor
|
||||
return view
|
||||
}()
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
@@ -121,13 +133,19 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
// MARK: - Private
|
||||
|
||||
private func setupUI() {
|
||||
view.addSubview(scrollIndicatorView)
|
||||
view.addSubview(tableView)
|
||||
|
||||
scrollIndicatorView.topAnchor.constraint(equalTo: tableView.topAnchor).isActive = true
|
||||
scrollIndicatorView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
scrollIndicatorView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
|
||||
scrollIndicatorView.widthAnchor.constraint(equalToConstant: 10.0).isActive = true
|
||||
|
||||
tableViewTopConstraint = tableView.topAnchor.constraint(equalTo: view.topAnchor)
|
||||
tableViewTopConstraint?.isActive = true
|
||||
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
|
||||
tableView.trailingAnchor.constraint(equalTo: scrollIndicatorView.leadingAnchor).isActive = true
|
||||
tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
|
||||
}
|
||||
|
||||
private func setupFilterView(isVisible: Bool) {
|
||||
@@ -246,6 +264,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
}
|
||||
|
||||
tableView.reloadData()
|
||||
updateCenterCellIndexPath()
|
||||
|
||||
if scrollToOpenedSeismic, let index = getSeismics().firstIndex(where: { isSeismicToHighlight(seismic: $0) }) {
|
||||
tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true)
|
||||
@@ -254,7 +273,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
}
|
||||
|
||||
private func loadAd() {
|
||||
adLoader.load(GADRequest())
|
||||
adLoader.load(Request())
|
||||
}
|
||||
|
||||
private func loadData(forced: Bool) {
|
||||
@@ -266,7 +285,8 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
let allSeismics = EQNManager.manager().retiSismiche
|
||||
let filteredSeismics = EQNSeismic.shared.filterSeismicList(allSeismics ?? [])
|
||||
rows = filteredSeismics.map { .seismic($0) }
|
||||
|
||||
seismicViewModels = filteredSeismics.map(SeismicNetworkViewModel.init)
|
||||
|
||||
#if ADS_ENABLED
|
||||
// if is not a pro user, show an advertise
|
||||
if !EQNPurchaseUtility.isProVersionEnabled() {
|
||||
@@ -278,6 +298,9 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
if let mapController = currentMapController {
|
||||
mapController.updateSeismics(filteredSeismics)
|
||||
}
|
||||
|
||||
scrollIndicatorView.seismics = seismicViewModels
|
||||
currentCenteredIndexPath = nil
|
||||
}
|
||||
|
||||
private func getSeismics() -> [EQNSisma] {
|
||||
@@ -560,6 +583,37 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
return false
|
||||
}
|
||||
|
||||
private func getCenterCellIndexPath() -> IndexPath? {
|
||||
let centerPoint = CGPoint(x: tableView.bounds.midX, y: tableView.bounds.midY)
|
||||
if let indexPath = tableView.indexPathForRow(at: centerPoint) {
|
||||
return indexPath
|
||||
}
|
||||
|
||||
// Se il metodo diretto fallisce, cerchiamo la cella più vicina
|
||||
if let visibleIndexPaths = tableView.indexPathsForVisibleRows {
|
||||
return visibleIndexPaths.min(by: { (indexPath1, indexPath2) -> Bool in
|
||||
let rect1 = tableView.rectForRow(at: indexPath1)
|
||||
let rect2 = tableView.rectForRow(at: indexPath2)
|
||||
let distance1 = abs(rect1.midY - centerPoint.y)
|
||||
let distance2 = abs(rect2.midY - centerPoint.y)
|
||||
return distance1 < distance2
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
private func updateCenterCellIndexPath() {
|
||||
if let centerIndexPath = getCenterCellIndexPath(), centerIndexPath != currentCenteredIndexPath {
|
||||
currentCenteredIndexPath = centerIndexPath
|
||||
|
||||
let row = rows[centerIndexPath.row]
|
||||
if case .seismic = row, seismicViewModels.count > centerIndexPath.row {
|
||||
scrollIndicatorView.highlighted = seismicViewModels[centerIndexPath.row]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction func refreshDataTapped(_ sender: Any) {
|
||||
@@ -618,6 +672,12 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UIScrollViewDelegate
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
updateCenterCellIndexPath()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func openCalendar(for seismic: EQNSisma) {
|
||||
@@ -673,18 +733,18 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
}
|
||||
}
|
||||
|
||||
extension SeismicNetworksViewController: GADNativeAdLoaderDelegate {
|
||||
func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) {
|
||||
print("[GADAdLoader] didReceive")
|
||||
extension SeismicNetworksViewController: NativeAdLoaderDelegate {
|
||||
func adLoader(_ adLoader: AdLoader, didReceive nativeAd: NativeAd) {
|
||||
print("[AdLoader] didReceive")
|
||||
|
||||
let adPosition = min(3, rows.count)
|
||||
rows.insert(.advertise(nativeAd), at: adPosition)
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) {
|
||||
func adLoader(_ adLoader: AdLoader, didFailToReceiveAdWithError error: Error) {
|
||||
// nope
|
||||
print("[GADAdLoader] didFailToReceiveAdWithError: \(error.localizedDescription)")
|
||||
print("[AdLoader] didFailToReceiveAdWithError: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -117,10 +117,20 @@ class SettingsRealTimeAlertsViewController: SettingsBaseTableViewController {
|
||||
}
|
||||
|
||||
private func onChangeCriticalAlertsEnabled(_ enabled: Bool) {
|
||||
if enabled {
|
||||
askForCriticalAlertsPermission()
|
||||
}
|
||||
|
||||
isCriticalAlertsEnabled = enabled
|
||||
EQNSettingRealTimeAlert.shared.isCriticalAlertsEnabled = isCriticalAlertsEnabled
|
||||
EQNSettingRealTimeAlert.shared.saveUserInfo()
|
||||
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
private func askForCriticalAlertsPermission() {
|
||||
UNUserNotificationCenter.current().requestAuthorization(options: [ .criticalAlert ]) { granted, error in
|
||||
// nope
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSCalendarsUsageDescription</key>
|
||||
<string>L'accesso al calendario è richiesto per poter salvare le informazioni dei sismi di interesse</string>
|
||||
<string>L'accesso al calendario è richiesto per poter salvare le informazioni dei sismi di interesse</string>
|
||||
<key>NSContactsUsageDescription</key>
|
||||
<string>L'accesso ai contatti è richiesto per poter aggiungere persone agli eventi creati</string>
|
||||
<string>L'accesso ai contatti è richiesto per poter aggiungere persone agli eventi creati</string>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string> Ci occorre la tua posizione per inviare messaggi precisi in caso di terremoto</string>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
@@ -65,9 +65,9 @@
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string> Ci occorre la tua posizione per inviare messaggi precisi in caso di terremoto</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>L'accesso alla libreria è richiesto per poter salvare le immagini generate dall'app</string>
|
||||
<string>L'accesso alla libreria è richiesto per poter salvare le immagini generate dall'app</string>
|
||||
<key>NSUserTrackingUsageDescription</key>
|
||||
<string>Il tracciamento serve a capire se la pubblicità dell'app è efficace</string>
|
||||
<string>Il tracciamento serve a capire se la pubblicità dell'app è efficace</string>
|
||||
<key>SKAdNetworkItems</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -104,5 +104,7 @@
|
||||
</array>
|
||||
<key>UIUserInterfaceStyle</key>
|
||||
<string>Light</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -18,11 +18,10 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
||||
print("[EQNUserDefaultsCommand] Start execute")
|
||||
|
||||
applyDefaultSettings()
|
||||
saveMissingValues()
|
||||
|
||||
migrationV5_3()
|
||||
migrationV5_4()
|
||||
migrationV5_8()
|
||||
migrationFirstAppStat()
|
||||
migrationCriticalAlerts()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -36,50 +35,6 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private func saveMissingValues() {
|
||||
// `raggio sismi forti` was not saved before v2.3
|
||||
if UserDefaults.standard.object(forKey: UserDefaults.AllertaSismicaRaggioSismiForti) == nil {
|
||||
UserDefaults.standard.set("600", forKey: UserDefaults.AllertaSismicaRaggioSismiForti)
|
||||
}
|
||||
}
|
||||
|
||||
private func migrationV5_3() {
|
||||
let migrationPerformed = UserDefaults.standard.bool(forKey: UserDefaults.AppMigrationV5_3)
|
||||
if migrationPerformed {
|
||||
print("[EQNUserDefaultsCommand] Migration v5.3 already performed")
|
||||
return
|
||||
}
|
||||
|
||||
// l'ultima posizione era salvata come array, la trasformiamo in valore singolo
|
||||
let lastLocations = EQNUtility.loadArray(of: CLLocation.self, fromUserDefaultsForKey: UserDefaults.UserDataLastLocation) as? [CLLocation]
|
||||
if let lastLocation = lastLocations?.last {
|
||||
UserDefaults.standard.removeObject(forKey: UserDefaults.UserDataLastLocation)
|
||||
EQNUserData.shared.saveLastLocation(lastLocation)
|
||||
}
|
||||
|
||||
// resettiamo il Firebase token in modo da ri-eseguire la procedura di registrazione corretta
|
||||
EQNUserData.shared.saveFirebaseToken(nil)
|
||||
|
||||
UserDefaults.standard.set(true, forKey: UserDefaults.AppMigrationV5_3)
|
||||
}
|
||||
|
||||
private func migrationV5_4() {
|
||||
let migrationPerformed = UserDefaults.standard.bool(forKey: UserDefaults.AppMigrationV5_4)
|
||||
if migrationPerformed {
|
||||
print("[EQNUserDefaultsCommand] Migration v5.4 already performed")
|
||||
return
|
||||
}
|
||||
|
||||
// migriamo l'ultima posizione negli user defaults condivisi
|
||||
let userDefaults = UserDefaults.standard
|
||||
let groupUserDefaults = UserDefaults.appGroup
|
||||
if let encodedLocation = userDefaults.object(forKey: UserDefaults.UserDataLastLocation) as? Data {
|
||||
groupUserDefaults?.set(encodedLocation, forKey: UserDefaults.UserDataLastLocation)
|
||||
}
|
||||
|
||||
userDefaults.set(true, forKey: UserDefaults.AppMigrationV5_4)
|
||||
}
|
||||
|
||||
private func migrationV5_8() {
|
||||
let migrationPerformed = UserDefaults.standard.bool(forKey: UserDefaults.AppMigrationV5_8)
|
||||
if migrationPerformed {
|
||||
@@ -115,4 +70,41 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
||||
|
||||
userDefaults.set(true, forKey: UserDefaults.AppMigrationV5_8)
|
||||
}
|
||||
|
||||
private func migrationFirstAppStat() {
|
||||
// before v5.8.2, first app start was defined using Firebase Token
|
||||
let userDefaults = UserDefaults.standard
|
||||
let firstAppStartExecuted = userDefaults.bool(forKey: UserDefaults.FirstAppStartExecuted)
|
||||
if firstAppStartExecuted {
|
||||
print("[EQNUserDefaultsCommand] First app start already executed")
|
||||
return
|
||||
}
|
||||
|
||||
let firebaseToken = userDefaults.object(forKey: UserDefaults.UserDataFirebaseToken) as? String
|
||||
if firebaseToken != nil {
|
||||
print("[EQNUserDefaultsCommand] First app start migrated")
|
||||
userDefaults.set(true, forKey: UserDefaults.FirstAppStartExecuted)
|
||||
}
|
||||
}
|
||||
|
||||
private func migrationCriticalAlerts() {
|
||||
let userDefaults = UserDefaults.standard
|
||||
let migrationPerformed = userDefaults.bool(forKey: UserDefaults.AppMigrationV5_8_2)
|
||||
if migrationPerformed {
|
||||
print("[EQNUserDefaultsCommand] Migration v5.8.2 already performed")
|
||||
return
|
||||
}
|
||||
|
||||
UNUserNotificationCenter.current().getNotificationSettings { settings in
|
||||
if settings.criticalAlertSetting != .enabled {
|
||||
print("[EQNUserDefaultsCommand] Critical alerts not enabled, disable settings")
|
||||
EQNSettingRealTimeAlert.shared.isCriticalAlertsEnabled = false
|
||||
EQNSettingRealTimeAlert.shared.saveUserInfo()
|
||||
} else {
|
||||
print("[EQNUserDefaultsCommand] Critical alerts enabled, do nothing")
|
||||
}
|
||||
}
|
||||
|
||||
userDefaults.set(true, forKey: UserDefaults.AppMigrationV5_8_2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
self.registrationInProgress = NO;
|
||||
self.user_ID = EQNUserData.sharedData.userId;
|
||||
self.lastPosition = EQNUserData.sharedData.lastLocation;
|
||||
self.currentFirebaseToken = EQNUserData.sharedData.firebaseToken;
|
||||
|
||||
[self registerForLocationUpdates];
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ import CoreLocation
|
||||
|
||||
@objc
|
||||
var isFirstStart: Bool {
|
||||
firebaseToken == nil
|
||||
let firstAppStartExecuted = UserDefaults.standard.bool(forKey: UserDefaults.FirstAppStartExecuted)
|
||||
return !firstAppStartExecuted
|
||||
}
|
||||
|
||||
// MARK: - Firebase Token
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
"options_official_maxdist" = "المسافة القصو";
|
||||
"options_notification_manual" = "إشعارات تقرير المستخدم";
|
||||
"options_notification_enable_manual" = "استلم الإخطارات للزلازل التي أبلغ عنها يدويا من قبل المستخدمين";
|
||||
"main_areacheck_message" = "في الوقت الحالي ، يوجد في منطقتك %s هواتف ذكية تراقب الزلازل في الوقت الفعلي. قدرة شبكة الهاتف الذكي على اكتشاف الزلازل في الوقت الفعلي هي%@. لتحسين اكتشاف الزلازل في منطقتك ، شارك التطبيق مع عائلتك وأصدقائك ، شكرًا!";
|
||||
"main_areacheck_message" = "في الوقت الحالي ، يوجد في منطقتك %@ هواتف ذكية تراقب الزلازل في الوقت الفعلي. لتحسين اكتشاف الزلازل في منطقتك ، شارك التطبيق مع عائلتك وأصدقائك ، شكرًا!";
|
||||
"main_version" = "نموذج";
|
||||
"app_name" = "منبه الزلازل";
|
||||
"official_depth" = "العمق:";
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
"globe_simulation_message1" = "Con este epicentro, deberías recibir la alerta %.0f segundos antes. Sin embargo, %.0f personas serán alertadas antes que tú. El tiempo de aviso será de %.0f segundos. Al suscribirse hoy al servicio de prioridad TOP 10K, solo %.0f personas recibirán la alerta antes que usted (en orden de distancia del epicentro)";
|
||||
"globe_simulation_message2" = "Con este epicentro, deberías recibir la alerta %.0f segundos antes. Sin embargo, %.0f personas serán alertadas antes que tú. Recibirá la alerta %.0f segundos después de las ondas sísmicas. Al suscribirse hoy al servicio de prioridad TOP 10K, solo %.0f personas recibirán la alerta antes que usted (en orden de distancia del epicentro)";
|
||||
"globe_simulation_message3" = "Con este epicentro, deberías recibir la alerta %.0f segundos antes. Sin embargo, %.0f personas serán alertadas antes que tú. Al suscribirse hoy al servicio de prioridad TOP 10K, solo %.0f personas recibirán la alerta antes que usted (en orden de distancia del epicentro)";
|
||||
"globe_simulation_message4" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. Solo %@ personas serán alertadas antes que tú";
|
||||
"globe_simulation_message4" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. Solo %.0f personas serán alertadas antes que tú";
|
||||
"globe_simulation_message5" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. %.0f personas serán alertadas antes que tú. Para aumentar el tiempo de advertencia, puede suscribirse al servicio de prioridad %@";
|
||||
"globe_simulation_message6" = "Con este epicentro, gracias al servicio de prioridad %@, deberías recibir la alerta %.0f segundos antes. ¡Serás la primera persona en ser alertada!";
|
||||
"globe_simulation_priority" = "Servicio prioritario";
|
||||
|
||||
Reference in New Issue
Block a user