Skip to content

Commit 30abcac

Browse files
committed
Add Share/OpenInApp extensions, design changes, bug fixes
1 parent ccd2c05 commit 30abcac

34 files changed

+1073
-189
lines changed

ForPDA.xcodeproj/project.pbxproj

Lines changed: 359 additions & 38 deletions
Large diffs are not rendered by default.

ForPDA.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 0 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ForPDA.xcodeproj/xcuserdata/subvert.xcuserdatad/xcschemes/xcschememanagement.plist

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
<key>orderHint</key>
3131
<integer>0</integer>
3232
</dict>
33+
<key>OpenInForPDA.xcscheme_^#shared#^_</key>
34+
<dict>
35+
<key>orderHint</key>
36+
<integer>2</integer>
37+
</dict>
3338
<key>Promises (Playground) 1.xcscheme</key>
3439
<dict>
3540
<key>isShown</key>
@@ -56,14 +61,14 @@
5661
<key>isShown</key>
5762
<false/>
5863
<key>orderHint</key>
59-
<integer>13</integer>
64+
<integer>7</integer>
6065
</dict>
6166
<key>Rx (Playground) 2.xcscheme</key>
6267
<dict>
6368
<key>isShown</key>
6469
<false/>
6570
<key>orderHint</key>
66-
<integer>14</integer>
71+
<integer>8</integer>
6772
</dict>
6873
<key>Rx (Playground) 3.xcscheme</key>
6974
<dict>
@@ -91,21 +96,31 @@
9196
<key>isShown</key>
9297
<false/>
9398
<key>orderHint</key>
94-
<integer>12</integer>
99+
<integer>3</integer>
100+
</dict>
101+
<key>ShareExtension.xcscheme_^#shared#^_</key>
102+
<dict>
103+
<key>orderHint</key>
104+
<integer>1</integer>
105+
</dict>
106+
<key>ShareForPDA.xcscheme_^#shared#^_</key>
107+
<dict>
108+
<key>orderHint</key>
109+
<integer>1</integer>
95110
</dict>
96111
<key>SnapKitPlayground (Playground) 1.xcscheme</key>
97112
<dict>
98113
<key>isShown</key>
99114
<false/>
100115
<key>orderHint</key>
101-
<integer>7</integer>
116+
<integer>10</integer>
102117
</dict>
103118
<key>SnapKitPlayground (Playground) 2.xcscheme</key>
104119
<dict>
105120
<key>isShown</key>
106121
<false/>
107122
<key>orderHint</key>
108-
<integer>8</integer>
123+
<integer>11</integer>
109124
</dict>
110125
<key>SnapKitPlayground (Playground) 3.xcscheme</key>
111126
<dict>
@@ -133,21 +148,21 @@
133148
<key>isShown</key>
134149
<false/>
135150
<key>orderHint</key>
136-
<integer>2</integer>
151+
<integer>9</integer>
137152
</dict>
138153
<key>SwiftRichString (Playground) 1.xcscheme</key>
139154
<dict>
140155
<key>isShown</key>
141156
<false/>
142157
<key>orderHint</key>
143-
<integer>4</integer>
158+
<integer>5</integer>
144159
</dict>
145160
<key>SwiftRichString (Playground) 2.xcscheme</key>
146161
<dict>
147162
<key>isShown</key>
148163
<false/>
149164
<key>orderHint</key>
150-
<integer>5</integer>
165+
<integer>6</integer>
151166
</dict>
152167
<key>SwiftRichString (Playground) 3.xcscheme</key>
153168
<dict>
@@ -175,7 +190,7 @@
175190
<key>isShown</key>
176191
<false/>
177192
<key>orderHint</key>
178-
<integer>3</integer>
193+
<integer>4</integer>
179194
</dict>
180195
<key>Tools for plug-in “RswiftModifyXcodePackages”.xcscheme</key>
181196
<dict>

ForPDA/Info.plist

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
<dict>
88
<key>CFBundleTypeRole</key>
99
<string>Editor</string>
10+
<key>CFBundleURLName</key>
11+
<string>com.subvert.forpda</string>
1012
<key>CFBundleURLSchemes</key>
1113
<array>
12-
<string>com.forpda</string>
14+
<string>forpda</string>
1315
</array>
1416
</dict>
1517
</array>

ForPDA/Resources/en.lproj/Localizable.strings

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,14 @@
9292
"captcha.uploading.failed" = "Captcha uploading failed";
9393
"login.failed.unknown.reasons" = "Something went wrong, try again later";
9494
"login" = "Log In";
95+
96+
// Special // todo remove after 0.4
97+
"update03" = "Update 0.3";
98+
"update03.text" =
99+
"This update introduces two new options for opening articles in the app through Safari:
100+
101+
1) Press the Share button and select ForPDA from the list
102+
2) Go to Settings > Safari > Extensions > Open in ForPDA > On, after that Safari will offer to open articles in the app
103+
104+
P.S. Any issues with article rendering can be reported through a long tap on the news / menu in the upper right corner of the article / linked chat in the settings";
105+
"update03.enable.extension" = "Enable extension";

ForPDA/Resources/ru.lproj/Localizable.strings

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,14 @@
9292
"captcha.uploading.failed" = "Не получилось отправить капчу";
9393
"login.failed.unknown.reasons" = "Что-то пошло не так, попробуйте позже";
9494
"login" = "Войти";
95+
96+
// Особое // todo убрать после 0.4
97+
"update03" = "Обновление 0.3";
98+
"update03.text" =
99+
"В этом обновлении появились две новые возможности открывать статьи в приложении через Safari:
100+
101+
1) Нажать на кнопку Поделиться и выбрать в списке ForPDA
102+
2) Зайти в Настройки > Safari > Расширения > Open in ForPDA > Вкл, после чего Safari будет предлагать открывать приложение само
103+
104+
P.S. Об ошибках отображения элементов в статьях можно сообщить через долгий тап в новостях / меню в верхнем правом углу статьи / чате указанном в настройках";
105+
"update03.enable.extension" = "Включить расширение";

ForPDA/Sources/Application/SceneDelegate.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,26 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
2727

2828
overrideApplicationThemeStyle(with: settingsService.getAppTheme())
2929
configureWKWebView()
30-
31-
try? DefaultRouter().navigate(to: RouteMap.tabBarScreen, with: nil)
30+
31+
if let url = connectionOptions.urlContexts.first?.url {
32+
// Cold start deeplink
33+
handleDeeplinkUrl(url)
34+
} else {
35+
try? DefaultRouter().navigate(to: RouteMap.tabBarScreen, with: nil)
36+
}
37+
}
38+
39+
private func handleDeeplinkUrl(_ url: URL) {
40+
if url.absoluteString == "forpda://article//" {
41+
// Если share в браузере не сработал, то открываем новости
42+
// todo обработать нормально
43+
try? DefaultRouter().navigate(to: RouteMap.newsScreen, with: nil)
44+
} else {
45+
let id = url.absoluteString.components(separatedBy: "article/")[1]
46+
let url = "https://4pda.to/\(id)"
47+
let article = Article(url: url, info: nil)
48+
try? DefaultRouter().navigate(to: RouteMap.articleScreen, with: article)
49+
}
3250
}
3351

3452
private func configureWKWebView() {
@@ -42,6 +60,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
4260
}
4361
}
4462

63+
// Opens on existing scene
64+
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
65+
if let url = URLContexts.first?.url {
66+
handleDeeplinkUrl(url)
67+
}
68+
}
69+
4570
func sceneDidDisconnect(_ scene: UIScene) { }
4671

4772
func sceneDidBecomeActive(_ scene: UIScene) { }

ForPDA/Sources/Models/Article.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import Foundation
99

1010
struct Article {
1111
let url: String
12+
var info: ArticleInfo?
13+
}
14+
15+
struct ArticleInfo {
1216
let title: String
1317
let description: String
1418
let imageUrl: String

ForPDA/Sources/Modules/Article/ArticlePresenter.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ final class ArticlePresenter: ArticlePresenterProtocol {
4343
guard let self else { return }
4444
switch result {
4545
case .success(let response):
46+
// Deeplink case
47+
if article.info == nil {
48+
let articleInfo = parsingService.parseArticleInfo(from: response)
49+
article.info = articleInfo
50+
DispatchQueue.main.async {
51+
self.view?.reconfigureHeader()
52+
}
53+
}
54+
4655
let elements = parsingService.parseArticle(from: response)
4756
DispatchQueue.main.async {
4857
self.view?.configureArticle(with: elements)

ForPDA/Sources/Modules/Article/ArticleVC.swift

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import NukeExtensions
1414

1515
protocol ArticleVCProtocol: AnyObject {
1616
func configureArticle(with elements: [ArticleElement])
17+
func reconfigureHeader()
1718
func makeComments(from page: String)
1819
func showError()
1920
}
@@ -49,7 +50,7 @@ final class ArticleVC: PDAViewController<ArticleView> {
4950
} else {
5051
myView.removeComments()
5152
let elements = ArticleBuilder.makeDefaultArticle(
52-
description: presenter.article.description,
53+
description: presenter.article.info?.description ?? "Ошибка",
5354
url: presenter.article.url
5455
)
5556
makeArticle(from: elements)
@@ -60,15 +61,18 @@ final class ArticleVC: PDAViewController<ArticleView> {
6061

6162
private func configureNavigationTitle() {
6263
let label = MarqueeLabel(frame: .zero, rate: 30, fadeLength: 0)
63-
label.text = presenter.article.title
64+
label.text = presenter.article.info?.title
6465
label.fadeLength = 30
6566
navigationItem.titleView = label
6667
}
6768

6869
private func configureView() {
69-
NukeExtensions.loadImage(with: URL(string: presenter.article.imageUrl)!, into: myView.articleImage)
70-
myView.titleLabel.text = presenter.article.title
71-
myView.commentsLabel.text = R.string.localizable.comments(Int(presenter.article.commentAmount) ?? 0)
70+
NukeExtensions.loadImage(with: URL(string: presenter.article.info?.imageUrl), into: myView.articleImage) { result in
71+
// Добавляем оверлей если открываем не через deeplink (?)
72+
if (try? result.get()) != nil { self.myView.articleImage.addoverlay() }
73+
}
74+
myView.titleLabel.text = presenter.article.info?.title
75+
myView.commentsLabel.text = R.string.localizable.comments(Int(presenter.article.info?.commentAmount ?? "0") ?? 0)
7276
}
7377

7478
private func configureMenu() {
@@ -149,7 +153,10 @@ final class ArticleVC: PDAViewController<ArticleView> {
149153
myView.stackView.addArrangedSubview(articleElement)
150154
}
151155

152-
myView.commentsContainer.isHidden = false
156+
// todo Почему без mainactor не работает?
157+
Task { @MainActor in
158+
myView.commentsContainer.isHidden = false
159+
}
153160
myView.stopLoading()
154161
}
155162

@@ -173,20 +180,23 @@ final class ArticleVC: PDAViewController<ArticleView> {
173180

174181
extension ArticleVC: ArticleVCProtocol {
175182

183+
func reconfigureHeader() {
184+
configureNavigationTitle()
185+
configureView()
186+
}
187+
176188
func configureArticle(with elements: [ArticleElement]) {
177-
DispatchQueue.main.async {
178-
self.makeArticle(from: elements)
179-
}
189+
makeArticle(from: elements)
180190
}
181191

182192
func showError() {
183-
DispatchQueue.main.async {
184-
let alert = UIAlertController(title: R.string.localizable.error(),
185-
message: R.string.localizable.somethingWentWrong(),
186-
preferredStyle: .alert)
187-
alert.addAction(UIAlertAction(title: R.string.localizable.ok(), style: .default))
188-
self.present(alert, animated: true)
189-
}
193+
let alert = UIAlertController(
194+
title: R.string.localizable.error(),
195+
message: R.string.localizable.somethingWentWrong(),
196+
preferredStyle: .alert
197+
)
198+
alert.addAction(UIAlertAction(title: R.string.localizable.ok(), style: .default))
199+
present(alert, animated: true)
190200
}
191201
}
192202

0 commit comments

Comments
 (0)