Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ jobs:
xcrun simctl list runtimes
- name: Ensure iOS platform runtimes
run: sudo xcodebuild -downloadPlatform iOS
- name: Create Secrets.xcconfig
run: |
mkdir -p Config
echo "GOOGLE_MAPS_API_KEY = ${{ secrets.GOOGLE_MAPS_API_KEY }}" > Config/Secrets.xcconfig
- name: Resolve Swift packages
run: xcodebuild -resolvePackageDependencies
- name: Build
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,7 @@ XcodeBuild/
# Claude Code configuration
CLAUDE.md

.DS_Store
.DS_Store

# Secrets (API keys)
/Config/Secrets.xcconfig
4 changes: 4 additions & 0 deletions Config/Secrets.xcconfig.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Secrets configuration file
// Copy this file to Secrets.xcconfig and replace with your actual API key

GOOGLE_MAPS_API_KEY = REPLACE_ME
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ Also in TestFlight: https://testflight.apple.com/join/vbJFFZgD
<img src="screenshots/phone/en/jpgs/compare.jpeg" width="19%" />
</p>

### Setup

1. Copy `Config/Secrets.xcconfig.example` to `Config/Secrets.xcconfig`
2. Replace `REPLACE_ME` with your Google Maps API key
3. Build and run

> **Note:** `Config/Secrets.xcconfig` is in `.gitignore` and should never be committed.

**CI:** Generate `Config/Secrets.xcconfig` from the `GOOGLE_MAPS_API_KEY` environment secret.

### Availability
iOS 18+

Expand Down
20 changes: 16 additions & 4 deletions Rewind.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
22291C882D50106600F2FEBE /* Rewind.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rewind.app; sourceTree = BUILT_PRODUCTS_DIR; };
22291C982D50106800F2FEBE /* RewindTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RewindTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
22291CA22D50106800F2FEBE /* RewindUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RewindUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4355A152FDB547CB9241A65F /* Secrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Secrets.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
Expand Down Expand Up @@ -103,6 +104,7 @@
22291C7F2D50106600F2FEBE = {
isa = PBXGroup;
children = (
26162C0FAABB4C9C9B7E32EE /* Config */,
22291C8A2D50106600F2FEBE /* Rewind */,
22291C892D50106600F2FEBE /* Products */,
);
Expand All @@ -118,6 +120,14 @@
name = Products;
sourceTree = "<group>";
};
26162C0FAABB4C9C9B7E32EE /* Config */ = {
isa = PBXGroup;
children = (
4355A152FDB547CB9241A65F /* Secrets.xcconfig */,
);
path = Config;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -431,11 +441,12 @@
};
22291CAD2D50106800F2FEBE /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4355A152FDB547CB9241A65F /* Secrets.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 16;
CURRENT_PROJECT_VERSION = 17;
DEVELOPMENT_ASSET_PATHS = "\"Rewind/Preview Content\"";
DEVELOPMENT_TEAM = AGFUBHFQD6;
ENABLE_PREVIEWS = YES;
Expand All @@ -453,7 +464,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.2;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = chizberg.Rewind;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand All @@ -464,11 +475,12 @@
};
22291CAE2D50106800F2FEBE /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4355A152FDB547CB9241A65F /* Secrets.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 16;
CURRENT_PROJECT_VERSION = 17;
DEVELOPMENT_ASSET_PATHS = "\"Rewind/Preview Content\"";
DEVELOPMENT_TEAM = AGFUBHFQD6;
ENABLE_PREVIEWS = YES;
Expand All @@ -486,7 +498,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.2;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = chizberg.Rewind;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down
2 changes: 2 additions & 0 deletions Rewind/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>GOOGLE_MAPS_API_KEY</key>
<string>$(GOOGLE_MAPS_API_KEY)</string>
<key>NSCameraUsageDescription</key>
<string>Camera access is needed to take comparison photos</string>
<key>NSPhotoLibraryAddUsageDescription</key>
Expand Down
128 changes: 123 additions & 5 deletions Rewind/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,31 @@
}
}
},
"2025" : {
"2026" : {
"comment" : "year from credits",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "2026"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "2025"
"value" : "2026"
}
},
"sr-Latn" : {
"stringUnit" : {
"state" : "translated",
"value" : "2025"
"value" : "2026"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "2025"
"value" : "2026"
}
}
}
Expand Down Expand Up @@ -317,6 +323,29 @@
}
}
},
"Compare with Google Street View" : {
"comment" : "Action of taking a photo of how the place looked like before and how it looks in google street view",
"localizations" : {
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Сравнить с панорамами Google"
}
},
"sr-Latn" : {
"stringUnit" : {
"state" : "translated",
"value" : "Uporedi sa Google Street View"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Порівняти з панорамами Google"
}
}
}
},
"comparison_description" : {
"comment" : "Onboarding description of a comparison feature",
"localizations" : {
Expand Down Expand Up @@ -582,6 +611,52 @@
}
}
},
"Google Street View is not available for this location." : {
"comment" : "error alert message",
"localizations" : {
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Панорамы Google недоступны для этого места."
}
},
"sr-Latn" : {
"stringUnit" : {
"state" : "translated",
"value" : "Google Street View nije dostupan za ovu lokaciju."
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Панорами Google недоступні для цього місця."
}
}
}
},
"Google Street View Unavailable" : {
"comment" : "error alert title",
"localizations" : {
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Google Street View недоступен"
}
},
"sr-Latn" : {
"stringUnit" : {
"state" : "translated",
"value" : "Google Street View nedostupan"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Google Street View недоступний"
}
}
}
},
"group_of_images_description" : {
"comment" : "Onboarding description of group of images annotation",
"localizations" : {
Expand Down Expand Up @@ -1637,6 +1712,29 @@
}
}
},
"Street View Error" : {
"comment" : "error alert title",
"localizations" : {
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ошибка Street View"
}
},
"sr-Latn" : {
"stringUnit" : {
"state" : "translated",
"value" : "Greška Street View"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Помилка Street View"
}
}
}
},
"The app has no access to your location" : {
"comment" : "error message in alert",
"localizations" : {
Expand Down Expand Up @@ -1914,7 +2012,27 @@
}
},
"Unable to switch lens" : {

"comment" : "error message in alert when camera lens can’t be switched",
"localizations" : {
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Не удалось сменить линзу"
}
},
"sr-Latn" : {
"stringUnit" : {
"state" : "translated",
"value" : "Nije moguće promeniti objektiv"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Не вдалося переключити об'єктив"
}
}
}
},
"Unable to use the camera" : {
"comment" : "error message for comparison screen whenever the camera session is not ready",
Expand Down
5 changes: 2 additions & 3 deletions Rewind/Model/AppGraph.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ final class AppGraph {
makeImageDetailsModel(
modelImage: image,
remote: remotes.imageDetails.mapArgs { image.cid },
image: image.image,
coordinate: image.coordinate,
openSource: source,
favoriteModel: favoritesModel.isFavorite(image),
showOnMap: { coordinate in
Expand All @@ -78,7 +76,8 @@ final class AppGraph {
},
canOpenURL: { UIApplication.shared.canOpenURL($0) },
urlOpener: urlOpener,
setOrientationLock: { weakSelf?.orientationLock?.value = $0 }
setOrientationLock: { weakSelf?.orientationLock?.value = $0 },
streetViewAvailability: remotes.streetViewAvailability
)
}
let searchModelFactory = {
Expand Down
Loading
Loading