{"id":26542359,"url":"https://github.com/5j54d93/google-blogger-ios-app","last_synced_at":"2025-11-05T01:01:32.886Z","repository":{"id":43398010,"uuid":"449766115","full_name":"5j54d93/Google-Blogger-iOS-App","owner":"5j54d93","description":"List posts with infinite scroll from Google Blogger API in MVVM architecture, and using SwiftUI to design like Medium iOS App, which could read, search, save, comment posts, and so many excellent features！","archived":false,"fork":false,"pushed_at":"2022-08-18T11:15:49.000Z","size":85644,"stargazers_count":12,"open_issues_count":0,"forks_count":7,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-05-20T22:42:57.236Z","etag":null,"topics":["api","apple","appstorage","asyncimage","blogger","coredata","google","guesture","infinite-scroll","ios","ipad","iphone","medium","mvvm","swift","swiftui","watchos","webkit","widget","xcode"],"latest_commit_sha":null,"homepage":"https://medium.com/海大-ios-app-程式設計/google-blogger-部落格-ios-app-7a11eb74df90","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/5j54d93.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"custom":["paypal.me/5j54d93","ethereum/0xf43b3B8B734A9aD9B9e18DBf1882053CC6D623de"]}},"created_at":"2022-01-19T16:19:04.000Z","updated_at":"2024-05-02T01:18:45.000Z","dependencies_parsed_at":"2022-08-24T13:10:13.582Z","dependency_job_id":null,"html_url":"https://github.com/5j54d93/Google-Blogger-iOS-App","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5j54d93%2FGoogle-Blogger-iOS-App","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5j54d93%2FGoogle-Blogger-iOS-App/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5j54d93%2FGoogle-Blogger-iOS-App/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5j54d93%2FGoogle-Blogger-iOS-App/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/5j54d93","download_url":"https://codeload.github.com/5j54d93/Google-Blogger-iOS-App/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244894308,"owners_count":20527678,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","apple","appstorage","asyncimage","blogger","coredata","google","guesture","infinite-scroll","ios","ipad","iphone","medium","mvvm","swift","swiftui","watchos","webkit","widget","xcode"],"created_at":"2025-03-22T02:16:43.872Z","updated_at":"2025-11-05T01:01:32.407Z","avatar_url":"https://github.com/5j54d93.png","language":"Swift","funding_links":["paypal.me/5j54d93","ethereum/0xf43b3B8B734A9aD9B9e18DBf1882053CC6D623de"],"categories":[],"sub_categories":[],"readme":"# Google Blogger iOS App\n\n[![Swift](https://github.com/5j54d93/Google-Blogger-iOS-App/actions/workflows/swift.yml/badge.svg)](https://github.com/5j54d93/Google-Blogger-iOS-App/actions/workflows/swift.yml)\n[![GitHub license](https://img.shields.io/github/license/5j54d93/My-Favorite-NETFLIX)](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/LICENSE)\n![GitHub Repo stars](https://img.shields.io/github/stars/5j54d93/Google-Blogger-iOS-App)\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/5j54d93/Google-Blogger-iOS-App)\n![GitHub repo size](https://img.shields.io/github/repo-size/5j54d93/Google-Blogger-iOS-App)\n![Platform](https://img.shields.io/badge/platform-iOS｜iPadOS｜watchOS｜macOS-lightgrey)\n\nList posts with infinite scroll from [**Google Blogger API**](https://developers.google.com/blogger/docs/3.0/using?hl=en) in MVVM architecture, and using [**SwiftUI**](https://developer.apple.com/xcode/swiftui/) to design like [**Medium iOS App**](https://apps.apple.com/tw/app/medium/id828256236), which could read, search, save, comment posts, and so many excellent features！\n\n\u003cimg src=\"https://repository-images.githubusercontent.com/449766115/7b89c8cc-714b-4329-8a6f-08d5bee6e2e6\"/\u003e\n\n\u003e **Demo GIF**：iPhone 13 Pro Max\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Home-Demo.gif\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Explore-Demo.gif\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Saved-Demo.gif\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Author-Demo.gif\" width='25%' height='100%'/\u003e\n\n\u003e YouTube Demo Video：[**youtu.be/xL209rnT73M**](https://youtu.be/xL209rnT73M)\n\n## Overview\n\n1. [**How To Use**](https://github.com/5j54d93/Google-Blogger-iOS-App#how-to-use)\n2. [**Architecture Design、Features、Explanation**](https://github.com/5j54d93/Google-Blogger-iOS-App#architecture-designfeaturesexplanation)\n   - [Models／BloggerFeedJSONModel](https://github.com/5j54d93/Google-Blogger-iOS-App#modelsbloggerfeedjsonmodel)\n   - [ContentView](https://github.com/5j54d93/Google-Blogger-iOS-App#contentview)\n   - [HomeView](https://github.com/5j54d93/Google-Blogger-iOS-App#homeview)\n     - [HomeTagView](https://github.com/5j54d93/Google-Blogger-iOS-App#hometagview)\n     - [AddTagButtomSheetView](https://github.com/5j54d93/Google-Blogger-iOS-App#addtagbuttomsheetview)\n     - [EntryRowView](https://github.com/5j54d93/Google-Blogger-iOS-App#entryrowview)\n     - [PostView](https://github.com/5j54d93/Google-Blogger-iOS-App#postview)\n   - [ExploreView](https://github.com/5j54d93/Google-Blogger-iOS-App#exploreview)\n   - [SavedView](https://github.com/5j54d93/Google-Blogger-iOS-App#savedview)\n   - [AuthorView](https://github.com/5j54d93/Google-Blogger-iOS-App#authorview)\n   - [Widget](https://github.com/5j54d93/Google-Blogger-iOS-App#widget)：iPad Pro（12.9-inch、5th generation）\n   - [Watch](https://github.com/5j54d93/Google-Blogger-iOS-App#watch)：Apple Watch Series 7 - 45mm\n3. [**License：MIT**](https://github.com/5j54d93/Google-Blogger-iOS-App#licensemit)\n\n## How To Use\n\n1. Simply click on the green「Code」button on top right\n2. click「Open with Xcode」\n3. Having fun to explore this Google Blogger iOS App！\n\nif nothing happen：\n\n- Download this repository via `git clone` or from [Releases](https://github.com/5j54d93/Google-Blogger-iOS-App/releases)\n\n```shell\ngit clone https://github.com/5j54d93/Google-Blogger-iOS-App --depth\n```\n\n## Architecture Design、Features、Explanation\n\n### [Models／BloggerFeedJSONModel](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Models/BloggerFeedJSONModel.swift)\n\n- use `CodingKey` to change label in JSON data fetched from API\n\n### [ContentView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/ContentView.swift)\n\n- `TabView`：[`HomeView()`](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Home/HomeView.swift)、[`ExploreView()`](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Explore/ExploreView.swift)、[`SavedView()`](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Saved/SavedView.swift)、[`AuthorView()`](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Author/AuthorView.swift)\n- use `.environment(\\.symbolVariants, .none)` to prevent `tabItem` with default `.fill` icon type\n  - only change `tabItem` icon type to `.fill` when selected\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Home-tabItem.png\" width='100%' height='100%'/\u003e\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Saved-tabItem.png\" width='100%' height='100%'/\u003e\n\n### [HomeView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Home/HomeView.swift)\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/HomeView.png\" width='100%' height='100%'/\u003e\n\n- Show「You're offline」if we can't fetch data from API\n- `.scrollTo()` top when user click on `TabView`'s `tabItem`\n- when there's more posts to load, show `ProgressView()` at list bottom with `.onAppear` to achieve infinite scroll\n- use `.refreshable` to let list could refresh when been pull down\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/You're-offline.png\" width='50%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Home-ProgressView.png\" width='50%' height='100%'/\u003e\n\n#### [HomeTagView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Home/HomeTagView.swift)\n\n- display tags with `ScrollView(.horizontal, showsIndicators: false)`\n- click first plus button could triger bottomSheet（[`AddTagButtomSheetView`](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Home/AddTagButtomSheetView.swift)）to add tag to `Core Data`\n- show tags that store in `Core Data`\n- `.onLongPressGesture` tag could show delete icon aside which on click could delet tag form `Core Data`\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/HomeTagView.png\" width='100%' height='100%'/\u003e\n\n#### [AddTagButtomSheetView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Home/AddTagButtomSheetView.swift)\n\n- couldn't add the same tag multiple times\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/AddTagButtomSheetView.png\" width='33%' height='100%'/\u003e \u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Add-same-tag.png\" width='33%' height='100%'/\u003e\n\n#### [EntryRowView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Home/HomeTagView.swift)\n\n- use `.prefix(3)` to only show the first 3 items in array with `ForEach`\n- deal with post's thumbnail url to get higher resolution image\n\n```swift\nlet resVarId = thumbnail.url.lastIndex(of: \"s\") ?? thumbnail.url.endIndex\nlet fullResUrl = thumbnail.url[..\u003cresVarId]\nAsyncImage(url: URL(string: fullResUrl + \"s480\")) { image in\n    image\n        .resizable()\n        .scaledToFill()\n} placeholder: {\n    Color.gray.overlay { ProgressView() }\n}\n.frame(width: 75, height: 75)\n.clipped()\n```\n\n- onClink to show `fullScreenCover` [PostView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Home/PostView.swift)\n- long press to show `contextMenu`\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Home-contextMenu.png\" width='50%' height='100%'/\u003e\n\n#### [PostView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Home/PostView.swift)\n\n- use `WebKit`：[`WKWebView`](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/WebKit/BrowserView.swift) to show web\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/PostView.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/PostView-share.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/PostView-more.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/PostView-display-settings.png\" width='25%' height='100%'/\u003e\n\n### [ExploreView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Explore/ExploreView.swift)\n\n- recommended search words（posts topics）with `ScrollView(.horizontal, showsIndicators: false)` from API\n- search post from API\n- show recommendation posts with different UI if there's no search word\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/ExploreView.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/ExploreView-contextMenu.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/ExploreView-with-search-word.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/ExploreView-contextMenu-with-search-word.png\" width='25%' height='100%'/\u003e\n\n### [SavedView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Saved/SavedView.swift)\n\n- if there's no posts saved in `Core Data`, click「Start browsing」could change tab to [`ExploreView`](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Explore/ExploreView.swift)\n- only show post title \u0026 post thumbnail when `List`：`editMode.isEditing`\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/SavedView.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/SavedView-with-saved-posts.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/EditNoteView.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/SavedEntryRowView-onDelete.png\" width='25%' height='100%'/\u003e\n\n### [AuthorView](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/Blogger/Views/Author/AuthorView.swift)\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/AuthorView-sheet.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/SettingView.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/TagListView.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Easter%20eggs.png\" width='25%' height='100%'/\u003e\n\n- if user click on version tag 5 times could change Blogger url in API to change this app's content！\n\n### [Widget](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/BloggerWidget/BloggerWidget.swift)\n\n\u003e **Widgets**：iPad Pro（12.9-inch、5th generation）\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/widgets.jpg\" width='100%' height='100%'/\u003e\n\n- 4 different size\n- UI design like [Apple News](https://www.apple.com/apple-news/)\n- data fetch from API to get the newest posts\n- we also call API on `getSnapshot` in addition to `getTimeline`\n\n### [Watch](https://github.com/5j54d93/Google-Blogger-iOS-App/tree/main/BloggerWatch%20WatchKit%20Extension)\n\n\u003e **watchOS**：Apple Watch Series 7 - 45mm\n\n\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Watch-1.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Watch-2.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Watch-3.png\" width='25%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/.github/assets/Watch-4.png\" width='25%' height='100%'/\u003e\n\n- UI design with SwiftUI\n- data fetch from API\n- two clickable `Button` in a row of `List`\n\n## License：MIT\n\nThis package is [MIT licensed](https://github.com/5j54d93/Google-Blogger-iOS-App/blob/main/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F5j54d93%2Fgoogle-blogger-ios-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F5j54d93%2Fgoogle-blogger-ios-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F5j54d93%2Fgoogle-blogger-ios-app/lists"}