Showing
52 changed files
with
4801 additions
and
0 deletions
Too many changes to show.
To preserve performance only 52 of 52+ files are displayed.
.DS_Store
0 → 100644
No preview for this file type
AdBlocker/ContentBlockerRequestHandler.swift
0 → 100644
1 | +// | |
2 | +// ContentBlockerRequestHandler.swift | |
3 | +// AdBlocker | |
4 | +// | |
5 | +// Created by Artem Talko on 24.10.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import MobileCoreServices | |
10 | + | |
11 | +class ContentBlockerRequestHandler: NSObject, NSExtensionRequestHandling { | |
12 | + | |
13 | + func beginRequest(with context: NSExtensionContext) { | |
14 | + let attachment = NSItemProvider(contentsOf: Bundle.main.url(forResource: "blockerList", withExtension: "json"))! | |
15 | + | |
16 | + let item = NSExtensionItem() | |
17 | + item.attachments = [attachment] | |
18 | + | |
19 | + context.completeRequest(returningItems: [item], completionHandler: nil) | |
20 | + } | |
21 | +} | ... | ... |
AdBlocker/Info.plist
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
3 | +<plist version="1.0"> | |
4 | +<dict> | |
5 | + <key>NSExtension</key> | |
6 | + <dict> | |
7 | + <key>NSExtensionPointIdentifier</key> | |
8 | + <string>com.apple.Safari.content-blocker</string> | |
9 | + <key>NSExtensionPrincipalClass</key> | |
10 | + <string>$(PRODUCT_MODULE_NAME).ContentBlockerRequestHandler</string> | |
11 | + </dict> | |
12 | +</dict> | |
13 | +</plist> | ... | ... |
browser.xcodeproj/project.pbxproj
0 → 100644
1 | +// !$*UTF8*$! | |
2 | +{ | |
3 | + archiveVersion = 1; | |
4 | + classes = { | |
5 | + }; | |
6 | + objectVersion = 56; | |
7 | + objects = { | |
8 | + | |
9 | +/* Begin PBXBuildFile section */ | |
10 | + 1904ED472AC56BDB0035DB66 /* FontsFree-Net-SFProText-Semibold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1904ED452AC56BDB0035DB66 /* FontsFree-Net-SFProText-Semibold.ttf */; }; | |
11 | + 1904ED482AC56BDB0035DB66 /* FontsFree-Net-SFProText-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1904ED462AC56BDB0035DB66 /* FontsFree-Net-SFProText-Regular.ttf */; }; | |
12 | + 1907D6972ADE766F00C40E9F /* HistoryDBManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1907D6962ADE766F00C40E9F /* HistoryDBManager.swift */; }; | |
13 | + 1907D6992ADE7E9C00C40E9F /* DateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1907D6982ADE7E9C00C40E9F /* DateManager.swift */; }; | |
14 | + 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190DB9FB2AC450F6000A7BF3 /* RemoveAdvertViewController.swift */; }; | |
15 | + 190DBA002AC45A3C000A7BF3 /* CachingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190DB9FF2AC45A3C000A7BF3 /* CachingManager.swift */; }; | |
16 | + 190DBA0D2AC47701000A7BF3 /* BinaryFloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190DBA0C2AC47701000A7BF3 /* BinaryFloatingPoint.swift */; }; | |
17 | + 191BB84F2AC5A9C900A2DEB9 /* TabsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB84E2AC5A9C900A2DEB9 /* TabsView.swift */; }; | |
18 | + 191BB8522AC5AB4600A2DEB9 /* TabsToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8512AC5AB4600A2DEB9 /* TabsToolbarView.swift */; }; | |
19 | + 191BB8542AC5B3CD00A2DEB9 /* TabsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8532AC5B3CD00A2DEB9 /* TabsViewController.swift */; }; | |
20 | + 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8562AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift */; }; | |
21 | + 191BB8622AC6A01500A2DEB9 /* SearchingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8612AC6A01500A2DEB9 /* SearchingViewController.swift */; }; | |
22 | + 191BB8642AC6A02300A2DEB9 /* SearchingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8632AC6A02300A2DEB9 /* SearchingView.swift */; }; | |
23 | + 191BB8692AC6A66900A2DEB9 /* SearchingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8682AC6A66900A2DEB9 /* SearchingTableViewCell.swift */; }; | |
24 | + 191BB8772AC6B47700A2DEB9 /* HistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8762AC6B47700A2DEB9 /* HistoryView.swift */; }; | |
25 | + 191BB8792AC6B48400A2DEB9 /* HistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8782AC6B48400A2DEB9 /* HistoryViewController.swift */; }; | |
26 | + 191BB87C2AC6B79C00A2DEB9 /* HistoryTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB87B2AC6B79C00A2DEB9 /* HistoryTableViewCell.swift */; }; | |
27 | + 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */; }; | |
28 | + 191BB8812AC6FF6600A2DEB9 /* RemoveAdvertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */; }; | |
29 | + 1926E82F2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1926E82E2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift */; }; | |
30 | + 193B3B832ACAF394002161ED /* BrowserTabDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */; }; | |
31 | + 193B3B862ACAF480002161ED /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 193B3B852ACAF480002161ED /* Realm */; }; | |
32 | + 193B3B882ACAF480002161ED /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 193B3B872ACAF480002161ED /* RealmSwift */; }; | |
33 | + 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193B3B892ACAF714002161ED /* TabManager.swift */; }; | |
34 | + 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194635D52ADD738E00993D91 /* HistoryDataBase.swift */; }; | |
35 | + 19696AF52AE80DBD00D1F8F9 /* blockerList.json in Resources */ = {isa = PBXBuildFile; fileRef = 19696AF42AE80DBD00D1F8F9 /* blockerList.json */; }; | |
36 | + 19696AF72AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */; }; | |
37 | + 19696AFB2AE80DBD00D1F8F9 /* AdBlocker.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; | |
38 | + 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */; }; | |
39 | + 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */; }; | |
40 | + 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */; }; | |
41 | + 197FC3F92AC2FB69007F429C /* SettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F82AC2FB69007F429C /* SettingViewController.swift */; }; | |
42 | + 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3FB2AC2FBA0007F429C /* SettingView.swift */; }; | |
43 | + 197FC3FF2AC30746007F429C /* SettingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3FE2AC30746007F429C /* SettingTableViewCell.swift */; }; | |
44 | + 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC4002AC31D5C007F429C /* NavigationViewController.swift */; }; | |
45 | + 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC4022AC41EB7007F429C /* ToolbarView.swift */; }; | |
46 | + 1984BF402AFB90560050F816 /* PrivacyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1984BF3F2AFB90560050F816 /* PrivacyViewController.swift */; }; | |
47 | + 1984BF422AFB907A0050F816 /* PrivacyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1984BF412AFB907A0050F816 /* PrivacyView.swift */; }; | |
48 | + 1984BF582AFB970F0050F816 /* TermsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1984BF572AFB970F0050F816 /* TermsViewController.swift */; }; | |
49 | + 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1984BF592AFB973C0050F816 /* TermsView.swift */; }; | |
50 | + 1989A1602AE29D4C00292680 /* OpenTabsTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1989A15F2AE29D4B00292680 /* OpenTabsTransition.swift */; }; | |
51 | + 1990C69C2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1990C69B2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift */; }; | |
52 | + 199DB1EE2AD3FCFE007E6A81 /* BrowserSearchService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 199DB1ED2AD3FCFE007E6A81 /* BrowserSearchService.swift */; }; | |
53 | + 199DB1F12AD3FDEE007E6A81 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 199DB1F02AD3FDEE007E6A81 /* Alamofire */; }; | |
54 | + 19B41DA12AD81A70002C0D31 /* SearchBarContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B41DA02AD81A70002C0D31 /* SearchBarContainer.swift */; }; | |
55 | + 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739692AE1554E0073AA59 /* URLConstants.swift */; }; | |
56 | + 19B7396E2AE156DE0073AA59 /* StringConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B7396D2AE156DE0073AA59 /* StringConstants.swift */; }; | |
57 | + 19B739712AE157900073AA59 /* FontConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739702AE157900073AA59 /* FontConstants.swift */; }; | |
58 | + 19B739732AE15B3B0073AA59 /* ColorConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739722AE15B3B0073AA59 /* ColorConstants.swift */; }; | |
59 | + 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739752AE276360073AA59 /* HistoryElement.swift */; }; | |
60 | + 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */; }; | |
61 | + 19C7A70C2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7A70B2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift */; }; | |
62 | + 19C7A70E2AC9F5FD00B954FC /* HistorySearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */; }; | |
63 | + 19CD89482AC719AC0035CB55 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD89472AC719AC0035CB55 /* SnapKit */; }; | |
64 | + 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */; }; | |
65 | + 19D8C9D62AE9169E0062D310 /* blockerList.json in Resources */ = {isa = PBXBuildFile; fileRef = 19696AF42AE80DBD00D1F8F9 /* blockerList.json */; }; | |
66 | + 19EECA452ACED45A00094AFB /* SearchResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19EECA442ACED45A00094AFB /* SearchResultView.swift */; }; | |
67 | + 19EECA472ACED48000094AFB /* SearchResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19EECA462ACED48000094AFB /* SearchResultViewController.swift */; }; | |
68 | + 19FCBF222AC1727800F83A7F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF212AC1727800F83A7F /* AppDelegate.swift */; }; | |
69 | + 19FCBF262AC1727800F83A7F /* BrowserHomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF252AC1727800F83A7F /* BrowserHomeViewController.swift */; }; | |
70 | + 19FCBF2B2AC1727900F83A7F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19FCBF2A2AC1727900F83A7F /* Assets.xcassets */; }; | |
71 | + 19FCBF2E2AC1727900F83A7F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19FCBF2C2AC1727900F83A7F /* LaunchScreen.storyboard */; }; | |
72 | + 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */; }; | |
73 | + 19FCBF452AC1981A00F83A7F /* TabCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */; }; | |
74 | + 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FFD6BE2AE64A7B00D0F768 /* SnapshotService.swift */; }; | |
75 | +/* End PBXBuildFile section */ | |
76 | + | |
77 | +/* Begin PBXContainerItemProxy section */ | |
78 | + 19696AF92AE80DBD00D1F8F9 /* PBXContainerItemProxy */ = { | |
79 | + isa = PBXContainerItemProxy; | |
80 | + containerPortal = 19FCBF162AC1727800F83A7F /* Project object */; | |
81 | + proxyType = 1; | |
82 | + remoteGlobalIDString = 19696AF12AE80DBC00D1F8F9; | |
83 | + remoteInfo = AdBlocker; | |
84 | + }; | |
85 | +/* End PBXContainerItemProxy section */ | |
86 | + | |
87 | +/* Begin PBXCopyFilesBuildPhase section */ | |
88 | + 19696AFC2AE80DBD00D1F8F9 /* Embed Foundation Extensions */ = { | |
89 | + isa = PBXCopyFilesBuildPhase; | |
90 | + buildActionMask = 2147483647; | |
91 | + dstPath = ""; | |
92 | + dstSubfolderSpec = 13; | |
93 | + files = ( | |
94 | + 19696AFB2AE80DBD00D1F8F9 /* AdBlocker.appex in Embed Foundation Extensions */, | |
95 | + ); | |
96 | + name = "Embed Foundation Extensions"; | |
97 | + runOnlyForDeploymentPostprocessing = 0; | |
98 | + }; | |
99 | +/* End PBXCopyFilesBuildPhase section */ | |
100 | + | |
101 | +/* Begin PBXFileReference section */ | |
102 | + 1904ED452AC56BDB0035DB66 /* FontsFree-Net-SFProText-Semibold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "FontsFree-Net-SFProText-Semibold.ttf"; sourceTree = "<group>"; }; | |
103 | + 1904ED462AC56BDB0035DB66 /* FontsFree-Net-SFProText-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "FontsFree-Net-SFProText-Regular.ttf"; sourceTree = "<group>"; }; | |
104 | + 1907D6962ADE766F00C40E9F /* HistoryDBManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryDBManager.swift; sourceTree = "<group>"; }; | |
105 | + 1907D6982ADE7E9C00C40E9F /* DateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateManager.swift; sourceTree = "<group>"; }; | |
106 | + 190DB9FB2AC450F6000A7BF3 /* RemoveAdvertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertViewController.swift; sourceTree = "<group>"; }; | |
107 | + 190DB9FF2AC45A3C000A7BF3 /* CachingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CachingManager.swift; sourceTree = "<group>"; }; | |
108 | + 190DBA0C2AC47701000A7BF3 /* BinaryFloatingPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinaryFloatingPoint.swift; sourceTree = "<group>"; }; | |
109 | + 191BB84E2AC5A9C900A2DEB9 /* TabsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsView.swift; sourceTree = "<group>"; }; | |
110 | + 191BB8512AC5AB4600A2DEB9 /* TabsToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsToolbarView.swift; sourceTree = "<group>"; }; | |
111 | + 191BB8532AC5B3CD00A2DEB9 /* TabsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsViewController.swift; sourceTree = "<group>"; }; | |
112 | + 191BB8562AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenedTabsCollectionViewCell.swift; sourceTree = "<group>"; }; | |
113 | + 191BB8612AC6A01500A2DEB9 /* SearchingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchingViewController.swift; sourceTree = "<group>"; }; | |
114 | + 191BB8632AC6A02300A2DEB9 /* SearchingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchingView.swift; sourceTree = "<group>"; }; | |
115 | + 191BB8682AC6A66900A2DEB9 /* SearchingTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchingTableViewCell.swift; sourceTree = "<group>"; }; | |
116 | + 191BB8762AC6B47700A2DEB9 /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = "<group>"; }; | |
117 | + 191BB8782AC6B48400A2DEB9 /* HistoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryViewController.swift; sourceTree = "<group>"; }; | |
118 | + 191BB87B2AC6B79C00A2DEB9 /* HistoryTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryTableViewCell.swift; sourceTree = "<group>"; }; | |
119 | + 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryToolbarView.swift; sourceTree = "<group>"; }; | |
120 | + 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertView.swift; sourceTree = "<group>"; }; | |
121 | + 1926E82E2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryToolbarMenuCases.swift; sourceTree = "<group>"; }; | |
122 | + 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserTabDataBase.swift; sourceTree = "<group>"; }; | |
123 | + 193B3B892ACAF714002161ED /* TabManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = "<group>"; }; | |
124 | + 194635D52ADD738E00993D91 /* HistoryDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryDataBase.swift; sourceTree = "<group>"; }; | |
125 | + 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = AdBlocker.appex; sourceTree = BUILT_PRODUCTS_DIR; }; | |
126 | + 19696AF42AE80DBD00D1F8F9 /* blockerList.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = blockerList.json; sourceTree = "<group>"; }; | |
127 | + 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBlockerRequestHandler.swift; sourceTree = "<group>"; }; | |
128 | + 19696AF82AE80DBD00D1F8F9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | |
129 | + 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadViewController.swift; sourceTree = "<group>"; }; | |
130 | + 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvantagesTableViewCell.swift; sourceTree = "<group>"; }; | |
131 | + 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarView.swift; sourceTree = "<group>"; }; | |
132 | + 197FC3F82AC2FB69007F429C /* SettingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewController.swift; sourceTree = "<group>"; }; | |
133 | + 197FC3FB2AC2FBA0007F429C /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = "<group>"; }; | |
134 | + 197FC3FE2AC30746007F429C /* SettingTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingTableViewCell.swift; sourceTree = "<group>"; }; | |
135 | + 197FC4002AC31D5C007F429C /* NavigationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewController.swift; sourceTree = "<group>"; }; | |
136 | + 197FC4022AC41EB7007F429C /* ToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarView.swift; sourceTree = "<group>"; }; | |
137 | + 1984BF3F2AFB90560050F816 /* PrivacyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyViewController.swift; sourceTree = "<group>"; }; | |
138 | + 1984BF412AFB907A0050F816 /* PrivacyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyView.swift; sourceTree = "<group>"; }; | |
139 | + 1984BF572AFB970F0050F816 /* TermsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsViewController.swift; sourceTree = "<group>"; }; | |
140 | + 1984BF592AFB973C0050F816 /* TermsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsView.swift; sourceTree = "<group>"; }; | |
141 | + 1989A15F2AE29D4B00292680 /* OpenTabsTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTabsTransition.swift; sourceTree = "<group>"; }; | |
142 | + 1990C69B2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionViewCell+convertFrameToScreenCoordinates.swift"; sourceTree = "<group>"; }; | |
143 | + 199DB1ED2AD3FCFE007E6A81 /* BrowserSearchService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserSearchService.swift; sourceTree = "<group>"; }; | |
144 | + 19B41DA02AD81A70002C0D31 /* SearchBarContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarContainer.swift; sourceTree = "<group>"; }; | |
145 | + 19B739692AE1554E0073AA59 /* URLConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLConstants.swift; sourceTree = "<group>"; }; | |
146 | + 19B7396D2AE156DE0073AA59 /* StringConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringConstants.swift; sourceTree = "<group>"; }; | |
147 | + 19B739702AE157900073AA59 /* FontConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontConstants.swift; sourceTree = "<group>"; }; | |
148 | + 19B739722AE15B3B0073AA59 /* ColorConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConstants.swift; sourceTree = "<group>"; }; | |
149 | + 19B739752AE276360073AA59 /* HistoryElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryElement.swift; sourceTree = "<group>"; }; | |
150 | + 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataExtention+toImage.swift"; sourceTree = "<group>"; }; | |
151 | + 19C7A70B2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertTableViewCell.swift; sourceTree = "<group>"; }; | |
152 | + 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistorySearchBarView.swift; sourceTree = "<group>"; }; | |
153 | + 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadView.swift; sourceTree = "<group>"; }; | |
154 | + 19EECA442ACED45A00094AFB /* SearchResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultView.swift; sourceTree = "<group>"; }; | |
155 | + 19EECA462ACED48000094AFB /* SearchResultViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultViewController.swift; sourceTree = "<group>"; }; | |
156 | + 19FCBF1E2AC1727800F83A7F /* browser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = browser.app; sourceTree = BUILT_PRODUCTS_DIR; }; | |
157 | + 19FCBF212AC1727800F83A7F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; | |
158 | + 19FCBF252AC1727800F83A7F /* BrowserHomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHomeViewController.swift; sourceTree = "<group>"; }; | |
159 | + 19FCBF2A2AC1727900F83A7F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; | |
160 | + 19FCBF2D2AC1727900F83A7F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; | |
161 | + 19FCBF2F2AC1727900F83A7F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | |
162 | + 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHomeView.swift; sourceTree = "<group>"; }; | |
163 | + 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabCollectionViewCell.swift; sourceTree = "<group>"; }; | |
164 | + 19FFD6BE2AE64A7B00D0F768 /* SnapshotService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotService.swift; sourceTree = "<group>"; }; | |
165 | +/* End PBXFileReference section */ | |
166 | + | |
167 | +/* Begin PBXFrameworksBuildPhase section */ | |
168 | + 19696AEF2AE80DBC00D1F8F9 /* Frameworks */ = { | |
169 | + isa = PBXFrameworksBuildPhase; | |
170 | + buildActionMask = 2147483647; | |
171 | + files = ( | |
172 | + ); | |
173 | + runOnlyForDeploymentPostprocessing = 0; | |
174 | + }; | |
175 | + 19FCBF1B2AC1727800F83A7F /* Frameworks */ = { | |
176 | + isa = PBXFrameworksBuildPhase; | |
177 | + buildActionMask = 2147483647; | |
178 | + files = ( | |
179 | + 193B3B882ACAF480002161ED /* RealmSwift in Frameworks */, | |
180 | + 199DB1F12AD3FDEE007E6A81 /* Alamofire in Frameworks */, | |
181 | + 193B3B862ACAF480002161ED /* Realm in Frameworks */, | |
182 | + 19CD89482AC719AC0035CB55 /* SnapKit in Frameworks */, | |
183 | + ); | |
184 | + runOnlyForDeploymentPostprocessing = 0; | |
185 | + }; | |
186 | +/* End PBXFrameworksBuildPhase section */ | |
187 | + | |
188 | +/* Begin PBXGroup section */ | |
189 | + 190DB9F72AC44FCA000A7BF3 /* RemoveAdvert */ = { | |
190 | + isa = PBXGroup; | |
191 | + children = ( | |
192 | + 190DB9F82AC44FD4000A7BF3 /* View */, | |
193 | + 190DB9F92AC44FD8000A7BF3 /* Controller */, | |
194 | + ); | |
195 | + path = RemoveAdvert; | |
196 | + sourceTree = "<group>"; | |
197 | + }; | |
198 | + 190DB9F82AC44FD4000A7BF3 /* View */ = { | |
199 | + isa = PBXGroup; | |
200 | + children = ( | |
201 | + 19C7A70A2AC9EB9B00B954FC /* Cell */, | |
202 | + 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */, | |
203 | + ); | |
204 | + path = View; | |
205 | + sourceTree = "<group>"; | |
206 | + }; | |
207 | + 190DB9F92AC44FD8000A7BF3 /* Controller */ = { | |
208 | + isa = PBXGroup; | |
209 | + children = ( | |
210 | + 190DB9FB2AC450F6000A7BF3 /* RemoveAdvertViewController.swift */, | |
211 | + ); | |
212 | + path = Controller; | |
213 | + sourceTree = "<group>"; | |
214 | + }; | |
215 | + 190DB9FD2AC459CD000A7BF3 /* Managers */ = { | |
216 | + isa = PBXGroup; | |
217 | + children = ( | |
218 | + 190DB9FF2AC45A3C000A7BF3 /* CachingManager.swift */, | |
219 | + 193B3B892ACAF714002161ED /* TabManager.swift */, | |
220 | + 1907D6962ADE766F00C40E9F /* HistoryDBManager.swift */, | |
221 | + 1907D6982ADE7E9C00C40E9F /* DateManager.swift */, | |
222 | + ); | |
223 | + path = Managers; | |
224 | + sourceTree = "<group>"; | |
225 | + }; | |
226 | + 190DBA012AC45CDA000A7BF3 /* Extentions */ = { | |
227 | + isa = PBXGroup; | |
228 | + children = ( | |
229 | + 190DBA0C2AC47701000A7BF3 /* BinaryFloatingPoint.swift */, | |
230 | + 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */, | |
231 | + 1990C69B2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift */, | |
232 | + ); | |
233 | + path = Extentions; | |
234 | + sourceTree = "<group>"; | |
235 | + }; | |
236 | + 190DBA042AC474C4000A7BF3 /* Fonts */ = { | |
237 | + isa = PBXGroup; | |
238 | + children = ( | |
239 | + 1904ED462AC56BDB0035DB66 /* FontsFree-Net-SFProText-Regular.ttf */, | |
240 | + 1904ED452AC56BDB0035DB66 /* FontsFree-Net-SFProText-Semibold.ttf */, | |
241 | + ); | |
242 | + path = Fonts; | |
243 | + sourceTree = "<group>"; | |
244 | + }; | |
245 | + 191BB84A2AC5A8EF00A2DEB9 /* Components */ = { | |
246 | + isa = PBXGroup; | |
247 | + children = ( | |
248 | + 197FC4022AC41EB7007F429C /* ToolbarView.swift */, | |
249 | + 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */, | |
250 | + 19B41DA02AD81A70002C0D31 /* SearchBarContainer.swift */, | |
251 | + ); | |
252 | + path = Components; | |
253 | + sourceTree = "<group>"; | |
254 | + }; | |
255 | + 191BB84B2AC5A9A600A2DEB9 /* Tabs */ = { | |
256 | + isa = PBXGroup; | |
257 | + children = ( | |
258 | + 191BB84D2AC5A9B400A2DEB9 /* View */, | |
259 | + 191BB84C2AC5A9AD00A2DEB9 /* Controller */, | |
260 | + ); | |
261 | + path = Tabs; | |
262 | + sourceTree = "<group>"; | |
263 | + }; | |
264 | + 191BB84C2AC5A9AD00A2DEB9 /* Controller */ = { | |
265 | + isa = PBXGroup; | |
266 | + children = ( | |
267 | + 191BB8532AC5B3CD00A2DEB9 /* TabsViewController.swift */, | |
268 | + ); | |
269 | + path = Controller; | |
270 | + sourceTree = "<group>"; | |
271 | + }; | |
272 | + 191BB84D2AC5A9B400A2DEB9 /* View */ = { | |
273 | + isa = PBXGroup; | |
274 | + children = ( | |
275 | + 191BB8552AC5B48F00A2DEB9 /* Cell */, | |
276 | + 191BB8502AC5AB2700A2DEB9 /* Components */, | |
277 | + 191BB84E2AC5A9C900A2DEB9 /* TabsView.swift */, | |
278 | + ); | |
279 | + path = View; | |
280 | + sourceTree = "<group>"; | |
281 | + }; | |
282 | + 191BB8502AC5AB2700A2DEB9 /* Components */ = { | |
283 | + isa = PBXGroup; | |
284 | + children = ( | |
285 | + 191BB8512AC5AB4600A2DEB9 /* TabsToolbarView.swift */, | |
286 | + ); | |
287 | + path = Components; | |
288 | + sourceTree = "<group>"; | |
289 | + }; | |
290 | + 191BB8552AC5B48F00A2DEB9 /* Cell */ = { | |
291 | + isa = PBXGroup; | |
292 | + children = ( | |
293 | + 191BB8562AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift */, | |
294 | + ); | |
295 | + path = Cell; | |
296 | + sourceTree = "<group>"; | |
297 | + }; | |
298 | + 191BB85D2AC69FC800A2DEB9 /* Searching */ = { | |
299 | + isa = PBXGroup; | |
300 | + children = ( | |
301 | + 191BB85F2AC69FDB00A2DEB9 /* View */, | |
302 | + 191BB85E2AC69FCC00A2DEB9 /* Controller */, | |
303 | + ); | |
304 | + path = Searching; | |
305 | + sourceTree = "<group>"; | |
306 | + }; | |
307 | + 191BB85E2AC69FCC00A2DEB9 /* Controller */ = { | |
308 | + isa = PBXGroup; | |
309 | + children = ( | |
310 | + 191BB8612AC6A01500A2DEB9 /* SearchingViewController.swift */, | |
311 | + ); | |
312 | + path = Controller; | |
313 | + sourceTree = "<group>"; | |
314 | + }; | |
315 | + 191BB85F2AC69FDB00A2DEB9 /* View */ = { | |
316 | + isa = PBXGroup; | |
317 | + children = ( | |
318 | + 191BB8672AC6A65600A2DEB9 /* Cell */, | |
319 | + 191BB8632AC6A02300A2DEB9 /* SearchingView.swift */, | |
320 | + ); | |
321 | + path = View; | |
322 | + sourceTree = "<group>"; | |
323 | + }; | |
324 | + 191BB8672AC6A65600A2DEB9 /* Cell */ = { | |
325 | + isa = PBXGroup; | |
326 | + children = ( | |
327 | + 191BB8682AC6A66900A2DEB9 /* SearchingTableViewCell.swift */, | |
328 | + ); | |
329 | + path = Cell; | |
330 | + sourceTree = "<group>"; | |
331 | + }; | |
332 | + 191BB8702AC6B19F00A2DEB9 /* History */ = { | |
333 | + isa = PBXGroup; | |
334 | + children = ( | |
335 | + 191BB8722AC6B26500A2DEB9 /* View */, | |
336 | + 191BB8712AC6B25300A2DEB9 /* Controller */, | |
337 | + ); | |
338 | + path = History; | |
339 | + sourceTree = "<group>"; | |
340 | + }; | |
341 | + 191BB8712AC6B25300A2DEB9 /* Controller */ = { | |
342 | + isa = PBXGroup; | |
343 | + children = ( | |
344 | + 191BB8782AC6B48400A2DEB9 /* HistoryViewController.swift */, | |
345 | + ); | |
346 | + path = Controller; | |
347 | + sourceTree = "<group>"; | |
348 | + }; | |
349 | + 191BB8722AC6B26500A2DEB9 /* View */ = { | |
350 | + isa = PBXGroup; | |
351 | + children = ( | |
352 | + 191BB87A2AC6B78800A2DEB9 /* Cell */, | |
353 | + 191BB87D2AC6BB6600A2DEB9 /* Components */, | |
354 | + 191BB8762AC6B47700A2DEB9 /* HistoryView.swift */, | |
355 | + ); | |
356 | + path = View; | |
357 | + sourceTree = "<group>"; | |
358 | + }; | |
359 | + 191BB87A2AC6B78800A2DEB9 /* Cell */ = { | |
360 | + isa = PBXGroup; | |
361 | + children = ( | |
362 | + 191BB87B2AC6B79C00A2DEB9 /* HistoryTableViewCell.swift */, | |
363 | + ); | |
364 | + path = Cell; | |
365 | + sourceTree = "<group>"; | |
366 | + }; | |
367 | + 191BB87D2AC6BB6600A2DEB9 /* Components */ = { | |
368 | + isa = PBXGroup; | |
369 | + children = ( | |
370 | + 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */, | |
371 | + 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */, | |
372 | + ); | |
373 | + path = Components; | |
374 | + sourceTree = "<group>"; | |
375 | + }; | |
376 | + 193B3B812ACAF36C002161ED /* DataBases */ = { | |
377 | + isa = PBXGroup; | |
378 | + children = ( | |
379 | + 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */, | |
380 | + 194635D52ADD738E00993D91 /* HistoryDataBase.swift */, | |
381 | + ); | |
382 | + path = DataBases; | |
383 | + sourceTree = "<group>"; | |
384 | + }; | |
385 | + 19696AF32AE80DBD00D1F8F9 /* AdBlocker */ = { | |
386 | + isa = PBXGroup; | |
387 | + children = ( | |
388 | + 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */, | |
389 | + 19696AF82AE80DBD00D1F8F9 /* Info.plist */, | |
390 | + ); | |
391 | + path = AdBlocker; | |
392 | + sourceTree = "<group>"; | |
393 | + }; | |
394 | + 197FC3F02AC2AF8A007F429C /* Cell */ = { | |
395 | + isa = PBXGroup; | |
396 | + children = ( | |
397 | + 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */, | |
398 | + ); | |
399 | + path = Cell; | |
400 | + sourceTree = "<group>"; | |
401 | + }; | |
402 | + 197FC3F52AC2F9FA007F429C /* Settings */ = { | |
403 | + isa = PBXGroup; | |
404 | + children = ( | |
405 | + 197FC3F72AC2FA0C007F429C /* View */, | |
406 | + 197FC3F62AC2FA06007F429C /* Controller */, | |
407 | + ); | |
408 | + path = Settings; | |
409 | + sourceTree = "<group>"; | |
410 | + }; | |
411 | + 197FC3F62AC2FA06007F429C /* Controller */ = { | |
412 | + isa = PBXGroup; | |
413 | + children = ( | |
414 | + 197FC3F82AC2FB69007F429C /* SettingViewController.swift */, | |
415 | + ); | |
416 | + path = Controller; | |
417 | + sourceTree = "<group>"; | |
418 | + }; | |
419 | + 197FC3F72AC2FA0C007F429C /* View */ = { | |
420 | + isa = PBXGroup; | |
421 | + children = ( | |
422 | + 1984BF3A2AFB8FFA0050F816 /* Components */, | |
423 | + 197FC3FD2AC30738007F429C /* Cell */, | |
424 | + 197FC3FB2AC2FBA0007F429C /* SettingView.swift */, | |
425 | + ); | |
426 | + path = View; | |
427 | + sourceTree = "<group>"; | |
428 | + }; | |
429 | + 197FC3FD2AC30738007F429C /* Cell */ = { | |
430 | + isa = PBXGroup; | |
431 | + children = ( | |
432 | + 197FC3FE2AC30746007F429C /* SettingTableViewCell.swift */, | |
433 | + ); | |
434 | + path = Cell; | |
435 | + sourceTree = "<group>"; | |
436 | + }; | |
437 | + 1984BF3A2AFB8FFA0050F816 /* Components */ = { | |
438 | + isa = PBXGroup; | |
439 | + children = ( | |
440 | + 1984BF432AFB955C0050F816 /* Terms */, | |
441 | + 1984BF3B2AFB902A0050F816 /* Privacy */, | |
442 | + ); | |
443 | + path = Components; | |
444 | + sourceTree = "<group>"; | |
445 | + }; | |
446 | + 1984BF3B2AFB902A0050F816 /* Privacy */ = { | |
447 | + isa = PBXGroup; | |
448 | + children = ( | |
449 | + 1984BF3E2AFB90430050F816 /* Controller */, | |
450 | + 1984BF3D2AFB903C0050F816 /* View */, | |
451 | + ); | |
452 | + path = Privacy; | |
453 | + sourceTree = "<group>"; | |
454 | + }; | |
455 | + 1984BF3D2AFB903C0050F816 /* View */ = { | |
456 | + isa = PBXGroup; | |
457 | + children = ( | |
458 | + 1984BF412AFB907A0050F816 /* PrivacyView.swift */, | |
459 | + ); | |
460 | + path = View; | |
461 | + sourceTree = "<group>"; | |
462 | + }; | |
463 | + 1984BF3E2AFB90430050F816 /* Controller */ = { | |
464 | + isa = PBXGroup; | |
465 | + children = ( | |
466 | + 1984BF3F2AFB90560050F816 /* PrivacyViewController.swift */, | |
467 | + ); | |
468 | + path = Controller; | |
469 | + sourceTree = "<group>"; | |
470 | + }; | |
471 | + 1984BF432AFB955C0050F816 /* Terms */ = { | |
472 | + isa = PBXGroup; | |
473 | + children = ( | |
474 | + 1984BF562AFB97030050F816 /* Controller */, | |
475 | + 1984BF552AFB96FE0050F816 /* View */, | |
476 | + ); | |
477 | + path = Terms; | |
478 | + sourceTree = "<group>"; | |
479 | + }; | |
480 | + 1984BF552AFB96FE0050F816 /* View */ = { | |
481 | + isa = PBXGroup; | |
482 | + children = ( | |
483 | + 1984BF592AFB973C0050F816 /* TermsView.swift */, | |
484 | + ); | |
485 | + path = View; | |
486 | + sourceTree = "<group>"; | |
487 | + }; | |
488 | + 1984BF562AFB97030050F816 /* Controller */ = { | |
489 | + isa = PBXGroup; | |
490 | + children = ( | |
491 | + 1984BF572AFB970F0050F816 /* TermsViewController.swift */, | |
492 | + ); | |
493 | + path = Controller; | |
494 | + sourceTree = "<group>"; | |
495 | + }; | |
496 | + 199DB1EC2AD3FCE1007E6A81 /* Services */ = { | |
497 | + isa = PBXGroup; | |
498 | + children = ( | |
499 | + 199DB1ED2AD3FCFE007E6A81 /* BrowserSearchService.swift */, | |
500 | + 19FFD6BE2AE64A7B00D0F768 /* SnapshotService.swift */, | |
501 | + ); | |
502 | + path = Services; | |
503 | + sourceTree = "<group>"; | |
504 | + }; | |
505 | + 19B2D0AF2ACDEAB600D20CE8 /* SearchResult */ = { | |
506 | + isa = PBXGroup; | |
507 | + children = ( | |
508 | + 19EECA432ACED43400094AFB /* View */, | |
509 | + 19B2D0B02ACDEB3500D20CE8 /* Controller */, | |
510 | + ); | |
511 | + path = SearchResult; | |
512 | + sourceTree = "<group>"; | |
513 | + }; | |
514 | + 19B2D0B02ACDEB3500D20CE8 /* Controller */ = { | |
515 | + isa = PBXGroup; | |
516 | + children = ( | |
517 | + 19EECA462ACED48000094AFB /* SearchResultViewController.swift */, | |
518 | + ); | |
519 | + path = Controller; | |
520 | + sourceTree = "<group>"; | |
521 | + }; | |
522 | + 19B7396B2AE155540073AA59 /* Images */ = { | |
523 | + isa = PBXGroup; | |
524 | + children = ( | |
525 | + 19FCBF2A2AC1727900F83A7F /* Assets.xcassets */, | |
526 | + ); | |
527 | + path = Images; | |
528 | + sourceTree = "<group>"; | |
529 | + }; | |
530 | + 19B7396C2AE1555F0073AA59 /* Other */ = { | |
531 | + isa = PBXGroup; | |
532 | + children = ( | |
533 | + 19FCBF2C2AC1727900F83A7F /* LaunchScreen.storyboard */, | |
534 | + ); | |
535 | + path = Other; | |
536 | + sourceTree = "<group>"; | |
537 | + }; | |
538 | + 19B7396F2AE1573B0073AA59 /* Constants */ = { | |
539 | + isa = PBXGroup; | |
540 | + children = ( | |
541 | + 19B739692AE1554E0073AA59 /* URLConstants.swift */, | |
542 | + 19B7396D2AE156DE0073AA59 /* StringConstants.swift */, | |
543 | + 19B739702AE157900073AA59 /* FontConstants.swift */, | |
544 | + 19B739722AE15B3B0073AA59 /* ColorConstants.swift */, | |
545 | + ); | |
546 | + path = Constants; | |
547 | + sourceTree = "<group>"; | |
548 | + }; | |
549 | + 19B739742AE275FF0073AA59 /* Models */ = { | |
550 | + isa = PBXGroup; | |
551 | + children = ( | |
552 | + 19B739752AE276360073AA59 /* HistoryElement.swift */, | |
553 | + 1926E82E2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift */, | |
554 | + ); | |
555 | + path = Models; | |
556 | + sourceTree = "<group>"; | |
557 | + }; | |
558 | + 19C7A70A2AC9EB9B00B954FC /* Cell */ = { | |
559 | + isa = PBXGroup; | |
560 | + children = ( | |
561 | + 19C7A70B2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift */, | |
562 | + ); | |
563 | + path = Cell; | |
564 | + sourceTree = "<group>"; | |
565 | + }; | |
566 | + 19D1F2DC2AC1EE6200510506 /* Payload */ = { | |
567 | + isa = PBXGroup; | |
568 | + children = ( | |
569 | + 19D1F2DE2AC1EF0400510506 /* View */, | |
570 | + 19D1F2DD2AC1EEF800510506 /* Controller */, | |
571 | + ); | |
572 | + path = Payload; | |
573 | + sourceTree = "<group>"; | |
574 | + }; | |
575 | + 19D1F2DD2AC1EEF800510506 /* Controller */ = { | |
576 | + isa = PBXGroup; | |
577 | + children = ( | |
578 | + 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */, | |
579 | + ); | |
580 | + path = Controller; | |
581 | + sourceTree = "<group>"; | |
582 | + }; | |
583 | + 19D1F2DE2AC1EF0400510506 /* View */ = { | |
584 | + isa = PBXGroup; | |
585 | + children = ( | |
586 | + 197FC3F02AC2AF8A007F429C /* Cell */, | |
587 | + 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */, | |
588 | + ); | |
589 | + path = View; | |
590 | + sourceTree = "<group>"; | |
591 | + }; | |
592 | + 19EECA432ACED43400094AFB /* View */ = { | |
593 | + isa = PBXGroup; | |
594 | + children = ( | |
595 | + 19EECA442ACED45A00094AFB /* SearchResultView.swift */, | |
596 | + ); | |
597 | + path = View; | |
598 | + sourceTree = "<group>"; | |
599 | + }; | |
600 | + 19F65A712ACBFCB500B50F61 /* Resources */ = { | |
601 | + isa = PBXGroup; | |
602 | + children = ( | |
603 | + 19696AF42AE80DBD00D1F8F9 /* blockerList.json */, | |
604 | + 19B7396F2AE1573B0073AA59 /* Constants */, | |
605 | + 19B7396B2AE155540073AA59 /* Images */, | |
606 | + 190DBA042AC474C4000A7BF3 /* Fonts */, | |
607 | + 19B7396C2AE1555F0073AA59 /* Other */, | |
608 | + ); | |
609 | + path = Resources; | |
610 | + sourceTree = "<group>"; | |
611 | + }; | |
612 | + 19F65A722ACBFD7300B50F61 /* Common */ = { | |
613 | + isa = PBXGroup; | |
614 | + children = ( | |
615 | + 19F65A732ACBFDD100B50F61 /* Transitions */, | |
616 | + ); | |
617 | + path = Common; | |
618 | + sourceTree = "<group>"; | |
619 | + }; | |
620 | + 19F65A732ACBFDD100B50F61 /* Transitions */ = { | |
621 | + isa = PBXGroup; | |
622 | + children = ( | |
623 | + 1989A15F2AE29D4B00292680 /* OpenTabsTransition.swift */, | |
624 | + ); | |
625 | + path = Transitions; | |
626 | + sourceTree = "<group>"; | |
627 | + }; | |
628 | + 19FCBF152AC1727800F83A7F = { | |
629 | + isa = PBXGroup; | |
630 | + children = ( | |
631 | + 19FCBF202AC1727800F83A7F /* browser */, | |
632 | + 19696AF32AE80DBD00D1F8F9 /* AdBlocker */, | |
633 | + 19FCBF1F2AC1727800F83A7F /* Products */, | |
634 | + ); | |
635 | + sourceTree = "<group>"; | |
636 | + }; | |
637 | + 19FCBF1F2AC1727800F83A7F /* Products */ = { | |
638 | + isa = PBXGroup; | |
639 | + children = ( | |
640 | + 19FCBF1E2AC1727800F83A7F /* browser.app */, | |
641 | + 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */, | |
642 | + ); | |
643 | + name = Products; | |
644 | + sourceTree = "<group>"; | |
645 | + }; | |
646 | + 19FCBF202AC1727800F83A7F /* browser */ = { | |
647 | + isa = PBXGroup; | |
648 | + children = ( | |
649 | + 19B739742AE275FF0073AA59 /* Models */, | |
650 | + 19FCBF382AC17A4800F83A7F /* Modules */, | |
651 | + 199DB1EC2AD3FCE1007E6A81 /* Services */, | |
652 | + 19F65A722ACBFD7300B50F61 /* Common */, | |
653 | + 190DBA012AC45CDA000A7BF3 /* Extentions */, | |
654 | + 193B3B812ACAF36C002161ED /* DataBases */, | |
655 | + 19F65A712ACBFCB500B50F61 /* Resources */, | |
656 | + 190DB9FD2AC459CD000A7BF3 /* Managers */, | |
657 | + 19FCBF352AC1779800F83A7F /* Navigation */, | |
658 | + 19FCBF212AC1727800F83A7F /* AppDelegate.swift */, | |
659 | + 19FCBF2F2AC1727900F83A7F /* Info.plist */, | |
660 | + ); | |
661 | + path = browser; | |
662 | + sourceTree = "<group>"; | |
663 | + }; | |
664 | + 19FCBF352AC1779800F83A7F /* Navigation */ = { | |
665 | + isa = PBXGroup; | |
666 | + children = ( | |
667 | + 197FC4002AC31D5C007F429C /* NavigationViewController.swift */, | |
668 | + ); | |
669 | + path = Navigation; | |
670 | + sourceTree = "<group>"; | |
671 | + }; | |
672 | + 19FCBF382AC17A4800F83A7F /* Modules */ = { | |
673 | + isa = PBXGroup; | |
674 | + children = ( | |
675 | + 19B2D0AF2ACDEAB600D20CE8 /* SearchResult */, | |
676 | + 191BB8702AC6B19F00A2DEB9 /* History */, | |
677 | + 191BB85D2AC69FC800A2DEB9 /* Searching */, | |
678 | + 191BB84B2AC5A9A600A2DEB9 /* Tabs */, | |
679 | + 190DB9F72AC44FCA000A7BF3 /* RemoveAdvert */, | |
680 | + 197FC3F52AC2F9FA007F429C /* Settings */, | |
681 | + 19D1F2DC2AC1EE6200510506 /* Payload */, | |
682 | + 19FCBF392AC17A6600F83A7F /* Home */, | |
683 | + ); | |
684 | + path = Modules; | |
685 | + sourceTree = "<group>"; | |
686 | + }; | |
687 | + 19FCBF392AC17A6600F83A7F /* Home */ = { | |
688 | + isa = PBXGroup; | |
689 | + children = ( | |
690 | + 19FCBF3B2AC17A8400F83A7F /* View */, | |
691 | + 19FCBF3A2AC17A7800F83A7F /* Controller */, | |
692 | + ); | |
693 | + path = Home; | |
694 | + sourceTree = "<group>"; | |
695 | + }; | |
696 | + 19FCBF3A2AC17A7800F83A7F /* Controller */ = { | |
697 | + isa = PBXGroup; | |
698 | + children = ( | |
699 | + 19FCBF252AC1727800F83A7F /* BrowserHomeViewController.swift */, | |
700 | + ); | |
701 | + path = Controller; | |
702 | + sourceTree = "<group>"; | |
703 | + }; | |
704 | + 19FCBF3B2AC17A8400F83A7F /* View */ = { | |
705 | + isa = PBXGroup; | |
706 | + children = ( | |
707 | + 19FCBF432AC197FD00F83A7F /* Cell */, | |
708 | + 191BB84A2AC5A8EF00A2DEB9 /* Components */, | |
709 | + 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */, | |
710 | + ); | |
711 | + path = View; | |
712 | + sourceTree = "<group>"; | |
713 | + }; | |
714 | + 19FCBF432AC197FD00F83A7F /* Cell */ = { | |
715 | + isa = PBXGroup; | |
716 | + children = ( | |
717 | + 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */, | |
718 | + ); | |
719 | + path = Cell; | |
720 | + sourceTree = "<group>"; | |
721 | + }; | |
722 | +/* End PBXGroup section */ | |
723 | + | |
724 | +/* Begin PBXNativeTarget section */ | |
725 | + 19696AF12AE80DBC00D1F8F9 /* AdBlocker */ = { | |
726 | + isa = PBXNativeTarget; | |
727 | + buildConfigurationList = 19696AFF2AE80DBD00D1F8F9 /* Build configuration list for PBXNativeTarget "AdBlocker" */; | |
728 | + buildPhases = ( | |
729 | + 19696AEE2AE80DBC00D1F8F9 /* Sources */, | |
730 | + 19696AEF2AE80DBC00D1F8F9 /* Frameworks */, | |
731 | + 19696AF02AE80DBC00D1F8F9 /* Resources */, | |
732 | + ); | |
733 | + buildRules = ( | |
734 | + ); | |
735 | + dependencies = ( | |
736 | + ); | |
737 | + name = AdBlocker; | |
738 | + productName = AdBlocker; | |
739 | + productReference = 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */; | |
740 | + productType = "com.apple.product-type.app-extension"; | |
741 | + }; | |
742 | + 19FCBF1D2AC1727800F83A7F /* browser */ = { | |
743 | + isa = PBXNativeTarget; | |
744 | + buildConfigurationList = 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "browser" */; | |
745 | + buildPhases = ( | |
746 | + 19FCBF1A2AC1727800F83A7F /* Sources */, | |
747 | + 19FCBF1B2AC1727800F83A7F /* Frameworks */, | |
748 | + 19FCBF1C2AC1727800F83A7F /* Resources */, | |
749 | + 19696AFC2AE80DBD00D1F8F9 /* Embed Foundation Extensions */, | |
750 | + ); | |
751 | + buildRules = ( | |
752 | + ); | |
753 | + dependencies = ( | |
754 | + 19696AFA2AE80DBD00D1F8F9 /* PBXTargetDependency */, | |
755 | + ); | |
756 | + name = browser; | |
757 | + packageProductDependencies = ( | |
758 | + 19CD89472AC719AC0035CB55 /* SnapKit */, | |
759 | + 193B3B852ACAF480002161ED /* Realm */, | |
760 | + 193B3B872ACAF480002161ED /* RealmSwift */, | |
761 | + 199DB1F02AD3FDEE007E6A81 /* Alamofire */, | |
762 | + ); | |
763 | + productName = browser; | |
764 | + productReference = 19FCBF1E2AC1727800F83A7F /* browser.app */; | |
765 | + productType = "com.apple.product-type.application"; | |
766 | + }; | |
767 | +/* End PBXNativeTarget section */ | |
768 | + | |
769 | +/* Begin PBXProject section */ | |
770 | + 19FCBF162AC1727800F83A7F /* Project object */ = { | |
771 | + isa = PBXProject; | |
772 | + attributes = { | |
773 | + BuildIndependentTargetsInParallel = 1; | |
774 | + LastSwiftUpdateCheck = 1500; | |
775 | + LastUpgradeCheck = 1500; | |
776 | + TargetAttributes = { | |
777 | + 19696AF12AE80DBC00D1F8F9 = { | |
778 | + CreatedOnToolsVersion = 15.0.1; | |
779 | + }; | |
780 | + 19FCBF1D2AC1727800F83A7F = { | |
781 | + CreatedOnToolsVersion = 15.0; | |
782 | + }; | |
783 | + }; | |
784 | + }; | |
785 | + buildConfigurationList = 19FCBF192AC1727800F83A7F /* Build configuration list for PBXProject "browser" */; | |
786 | + compatibilityVersion = "Xcode 14.0"; | |
787 | + developmentRegion = en; | |
788 | + hasScannedForEncodings = 0; | |
789 | + knownRegions = ( | |
790 | + en, | |
791 | + Base, | |
792 | + ); | |
793 | + mainGroup = 19FCBF152AC1727800F83A7F; | |
794 | + packageReferences = ( | |
795 | + 19CD89462AC719AB0035CB55 /* XCRemoteSwiftPackageReference "SnapKit" */, | |
796 | + 193B3B842ACAF480002161ED /* XCRemoteSwiftPackageReference "realm-swift" */, | |
797 | + 199DB1EF2AD3FDEE007E6A81 /* XCRemoteSwiftPackageReference "Alamofire" */, | |
798 | + ); | |
799 | + productRefGroup = 19FCBF1F2AC1727800F83A7F /* Products */; | |
800 | + projectDirPath = ""; | |
801 | + projectRoot = ""; | |
802 | + targets = ( | |
803 | + 19FCBF1D2AC1727800F83A7F /* browser */, | |
804 | + 19696AF12AE80DBC00D1F8F9 /* AdBlocker */, | |
805 | + ); | |
806 | + }; | |
807 | +/* End PBXProject section */ | |
808 | + | |
809 | +/* Begin PBXResourcesBuildPhase section */ | |
810 | + 19696AF02AE80DBC00D1F8F9 /* Resources */ = { | |
811 | + isa = PBXResourcesBuildPhase; | |
812 | + buildActionMask = 2147483647; | |
813 | + files = ( | |
814 | + 19696AF52AE80DBD00D1F8F9 /* blockerList.json in Resources */, | |
815 | + ); | |
816 | + runOnlyForDeploymentPostprocessing = 0; | |
817 | + }; | |
818 | + 19FCBF1C2AC1727800F83A7F /* Resources */ = { | |
819 | + isa = PBXResourcesBuildPhase; | |
820 | + buildActionMask = 2147483647; | |
821 | + files = ( | |
822 | + 1904ED472AC56BDB0035DB66 /* FontsFree-Net-SFProText-Semibold.ttf in Resources */, | |
823 | + 19FCBF2E2AC1727900F83A7F /* LaunchScreen.storyboard in Resources */, | |
824 | + 1904ED482AC56BDB0035DB66 /* FontsFree-Net-SFProText-Regular.ttf in Resources */, | |
825 | + 19FCBF2B2AC1727900F83A7F /* Assets.xcassets in Resources */, | |
826 | + 19D8C9D62AE9169E0062D310 /* blockerList.json in Resources */, | |
827 | + ); | |
828 | + runOnlyForDeploymentPostprocessing = 0; | |
829 | + }; | |
830 | +/* End PBXResourcesBuildPhase section */ | |
831 | + | |
832 | +/* Begin PBXSourcesBuildPhase section */ | |
833 | + 19696AEE2AE80DBC00D1F8F9 /* Sources */ = { | |
834 | + isa = PBXSourcesBuildPhase; | |
835 | + buildActionMask = 2147483647; | |
836 | + files = ( | |
837 | + 19696AF72AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift in Sources */, | |
838 | + ); | |
839 | + runOnlyForDeploymentPostprocessing = 0; | |
840 | + }; | |
841 | + 19FCBF1A2AC1727800F83A7F /* Sources */ = { | |
842 | + isa = PBXSourcesBuildPhase; | |
843 | + buildActionMask = 2147483647; | |
844 | + files = ( | |
845 | + 19B739712AE157900073AA59 /* FontConstants.swift in Sources */, | |
846 | + 191BB8812AC6FF6600A2DEB9 /* RemoveAdvertView.swift in Sources */, | |
847 | + 191BB8792AC6B48400A2DEB9 /* HistoryViewController.swift in Sources */, | |
848 | + 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */, | |
849 | + 19B739732AE15B3B0073AA59 /* ColorConstants.swift in Sources */, | |
850 | + 19FCBF262AC1727800F83A7F /* BrowserHomeViewController.swift in Sources */, | |
851 | + 197FC3FF2AC30746007F429C /* SettingTableViewCell.swift in Sources */, | |
852 | + 19B41DA12AD81A70002C0D31 /* SearchBarContainer.swift in Sources */, | |
853 | + 19EECA452ACED45A00094AFB /* SearchResultView.swift in Sources */, | |
854 | + 1907D6972ADE766F00C40E9F /* HistoryDBManager.swift in Sources */, | |
855 | + 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */, | |
856 | + 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */, | |
857 | + 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */, | |
858 | + 19EECA472ACED48000094AFB /* SearchResultViewController.swift in Sources */, | |
859 | + 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */, | |
860 | + 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */, | |
861 | + 193B3B832ACAF394002161ED /* BrowserTabDataBase.swift in Sources */, | |
862 | + 1984BF402AFB90560050F816 /* PrivacyViewController.swift in Sources */, | |
863 | + 199DB1EE2AD3FCFE007E6A81 /* BrowserSearchService.swift in Sources */, | |
864 | + 1907D6992ADE7E9C00C40E9F /* DateManager.swift in Sources */, | |
865 | + 191BB8522AC5AB4600A2DEB9 /* TabsToolbarView.swift in Sources */, | |
866 | + 191BB84F2AC5A9C900A2DEB9 /* TabsView.swift in Sources */, | |
867 | + 19FCBF452AC1981A00F83A7F /* TabCollectionViewCell.swift in Sources */, | |
868 | + 19B7396E2AE156DE0073AA59 /* StringConstants.swift in Sources */, | |
869 | + 191BB8542AC5B3CD00A2DEB9 /* TabsViewController.swift in Sources */, | |
870 | + 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */, | |
871 | + 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */, | |
872 | + 191BB8642AC6A02300A2DEB9 /* SearchingView.swift in Sources */, | |
873 | + 190DBA002AC45A3C000A7BF3 /* CachingManager.swift in Sources */, | |
874 | + 1984BF422AFB907A0050F816 /* PrivacyView.swift in Sources */, | |
875 | + 191BB8692AC6A66900A2DEB9 /* SearchingTableViewCell.swift in Sources */, | |
876 | + 1990C69C2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift in Sources */, | |
877 | + 19FCBF222AC1727800F83A7F /* AppDelegate.swift in Sources */, | |
878 | + 19C7A70C2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift in Sources */, | |
879 | + 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */, | |
880 | + 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */, | |
881 | + 190DBA0D2AC47701000A7BF3 /* BinaryFloatingPoint.swift in Sources */, | |
882 | + 191BB8772AC6B47700A2DEB9 /* HistoryView.swift in Sources */, | |
883 | + 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */, | |
884 | + 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */, | |
885 | + 1984BF582AFB970F0050F816 /* TermsViewController.swift in Sources */, | |
886 | + 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */, | |
887 | + 191BB87C2AC6B79C00A2DEB9 /* HistoryTableViewCell.swift in Sources */, | |
888 | + 1926E82F2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift in Sources */, | |
889 | + 197FC3F92AC2FB69007F429C /* SettingViewController.swift in Sources */, | |
890 | + 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */, | |
891 | + 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */, | |
892 | + 191BB8622AC6A01500A2DEB9 /* SearchingViewController.swift in Sources */, | |
893 | + 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */, | |
894 | + 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */, | |
895 | + 1989A1602AE29D4C00292680 /* OpenTabsTransition.swift in Sources */, | |
896 | + 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */, | |
897 | + 19C7A70E2AC9F5FD00B954FC /* HistorySearchBarView.swift in Sources */, | |
898 | + ); | |
899 | + runOnlyForDeploymentPostprocessing = 0; | |
900 | + }; | |
901 | +/* End PBXSourcesBuildPhase section */ | |
902 | + | |
903 | +/* Begin PBXTargetDependency section */ | |
904 | + 19696AFA2AE80DBD00D1F8F9 /* PBXTargetDependency */ = { | |
905 | + isa = PBXTargetDependency; | |
906 | + target = 19696AF12AE80DBC00D1F8F9 /* AdBlocker */; | |
907 | + targetProxy = 19696AF92AE80DBD00D1F8F9 /* PBXContainerItemProxy */; | |
908 | + }; | |
909 | +/* End PBXTargetDependency section */ | |
910 | + | |
911 | +/* Begin PBXVariantGroup section */ | |
912 | + 19FCBF2C2AC1727900F83A7F /* LaunchScreen.storyboard */ = { | |
913 | + isa = PBXVariantGroup; | |
914 | + children = ( | |
915 | + 19FCBF2D2AC1727900F83A7F /* Base */, | |
916 | + ); | |
917 | + name = LaunchScreen.storyboard; | |
918 | + sourceTree = "<group>"; | |
919 | + }; | |
920 | +/* End PBXVariantGroup section */ | |
921 | + | |
922 | +/* Begin XCBuildConfiguration section */ | |
923 | + 19696AFD2AE80DBD00D1F8F9 /* Debug */ = { | |
924 | + isa = XCBuildConfiguration; | |
925 | + buildSettings = { | |
926 | + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; | |
927 | + CODE_SIGN_STYLE = Automatic; | |
928 | + CURRENT_PROJECT_VERSION = 1; | |
929 | + DEVELOPMENT_TEAM = 6Y97YM76EY; | |
930 | + GENERATE_INFOPLIST_FILE = YES; | |
931 | + INFOPLIST_FILE = AdBlocker/Info.plist; | |
932 | + INFOPLIST_KEY_CFBundleDisplayName = AdBlocker; | |
933 | + INFOPLIST_KEY_NSHumanReadableCopyright = ""; | |
934 | + IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |
935 | + LD_RUNPATH_SEARCH_PATHS = ( | |
936 | + "$(inherited)", | |
937 | + "@executable_path/Frameworks", | |
938 | + "@executable_path/../../Frameworks", | |
939 | + ); | |
940 | + MARKETING_VERSION = 1.0; | |
941 | + PRODUCT_BUNDLE_IDENTIFIER = "com.4k-soft.browser.AdBlock"; | |
942 | + PRODUCT_NAME = "$(TARGET_NAME)"; | |
943 | + SKIP_INSTALL = YES; | |
944 | + SWIFT_EMIT_LOC_STRINGS = YES; | |
945 | + SWIFT_VERSION = 5.0; | |
946 | + TARGETED_DEVICE_FAMILY = "1,2"; | |
947 | + }; | |
948 | + name = Debug; | |
949 | + }; | |
950 | + 19696AFE2AE80DBD00D1F8F9 /* Release */ = { | |
951 | + isa = XCBuildConfiguration; | |
952 | + buildSettings = { | |
953 | + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; | |
954 | + CODE_SIGN_STYLE = Automatic; | |
955 | + CURRENT_PROJECT_VERSION = 1; | |
956 | + DEVELOPMENT_TEAM = 6Y97YM76EY; | |
957 | + GENERATE_INFOPLIST_FILE = YES; | |
958 | + INFOPLIST_FILE = AdBlocker/Info.plist; | |
959 | + INFOPLIST_KEY_CFBundleDisplayName = AdBlocker; | |
960 | + INFOPLIST_KEY_NSHumanReadableCopyright = ""; | |
961 | + IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |
962 | + LD_RUNPATH_SEARCH_PATHS = ( | |
963 | + "$(inherited)", | |
964 | + "@executable_path/Frameworks", | |
965 | + "@executable_path/../../Frameworks", | |
966 | + ); | |
967 | + MARKETING_VERSION = 1.0; | |
968 | + PRODUCT_BUNDLE_IDENTIFIER = "com.4k-soft.browser.AdBlock"; | |
969 | + PRODUCT_NAME = "$(TARGET_NAME)"; | |
970 | + SKIP_INSTALL = YES; | |
971 | + SWIFT_EMIT_LOC_STRINGS = YES; | |
972 | + SWIFT_VERSION = 5.0; | |
973 | + TARGETED_DEVICE_FAMILY = "1,2"; | |
974 | + }; | |
975 | + name = Release; | |
976 | + }; | |
977 | + 19FCBF302AC1727900F83A7F /* Debug */ = { | |
978 | + isa = XCBuildConfiguration; | |
979 | + buildSettings = { | |
980 | + ALWAYS_SEARCH_USER_PATHS = NO; | |
981 | + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; | |
982 | + CLANG_ANALYZER_NONNULL = YES; | |
983 | + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; | |
984 | + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; | |
985 | + CLANG_ENABLE_MODULES = YES; | |
986 | + CLANG_ENABLE_OBJC_ARC = YES; | |
987 | + CLANG_ENABLE_OBJC_WEAK = YES; | |
988 | + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |
989 | + CLANG_WARN_BOOL_CONVERSION = YES; | |
990 | + CLANG_WARN_COMMA = YES; | |
991 | + CLANG_WARN_CONSTANT_CONVERSION = YES; | |
992 | + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |
993 | + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |
994 | + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; | |
995 | + CLANG_WARN_EMPTY_BODY = YES; | |
996 | + CLANG_WARN_ENUM_CONVERSION = YES; | |
997 | + CLANG_WARN_INFINITE_RECURSION = YES; | |
998 | + CLANG_WARN_INT_CONVERSION = YES; | |
999 | + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |
1000 | + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |
1001 | + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |
1002 | + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |
1003 | + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; | |
1004 | + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |
1005 | + CLANG_WARN_STRICT_PROTOTYPES = YES; | |
1006 | + CLANG_WARN_SUSPICIOUS_MOVE = YES; | |
1007 | + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; | |
1008 | + CLANG_WARN_UNREACHABLE_CODE = YES; | |
1009 | + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |
1010 | + COPY_PHASE_STRIP = NO; | |
1011 | + DEBUG_INFORMATION_FORMAT = dwarf; | |
1012 | + ENABLE_STRICT_OBJC_MSGSEND = YES; | |
1013 | + ENABLE_TESTABILITY = YES; | |
1014 | + ENABLE_USER_SCRIPT_SANDBOXING = YES; | |
1015 | + GCC_C_LANGUAGE_STANDARD = gnu17; | |
1016 | + GCC_DYNAMIC_NO_PIC = NO; | |
1017 | + GCC_NO_COMMON_BLOCKS = YES; | |
1018 | + GCC_OPTIMIZATION_LEVEL = 0; | |
1019 | + GCC_PREPROCESSOR_DEFINITIONS = ( | |
1020 | + "DEBUG=1", | |
1021 | + "$(inherited)", | |
1022 | + ); | |
1023 | + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |
1024 | + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |
1025 | + GCC_WARN_UNDECLARED_SELECTOR = YES; | |
1026 | + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |
1027 | + GCC_WARN_UNUSED_FUNCTION = YES; | |
1028 | + GCC_WARN_UNUSED_VARIABLE = YES; | |
1029 | + IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |
1030 | + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; | |
1031 | + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; | |
1032 | + MTL_FAST_MATH = YES; | |
1033 | + ONLY_ACTIVE_ARCH = YES; | |
1034 | + SDKROOT = iphoneos; | |
1035 | + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; | |
1036 | + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | |
1037 | + }; | |
1038 | + name = Debug; | |
1039 | + }; | |
1040 | + 19FCBF312AC1727900F83A7F /* Release */ = { | |
1041 | + isa = XCBuildConfiguration; | |
1042 | + buildSettings = { | |
1043 | + ALWAYS_SEARCH_USER_PATHS = NO; | |
1044 | + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; | |
1045 | + CLANG_ANALYZER_NONNULL = YES; | |
1046 | + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; | |
1047 | + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; | |
1048 | + CLANG_ENABLE_MODULES = YES; | |
1049 | + CLANG_ENABLE_OBJC_ARC = YES; | |
1050 | + CLANG_ENABLE_OBJC_WEAK = YES; | |
1051 | + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |
1052 | + CLANG_WARN_BOOL_CONVERSION = YES; | |
1053 | + CLANG_WARN_COMMA = YES; | |
1054 | + CLANG_WARN_CONSTANT_CONVERSION = YES; | |
1055 | + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |
1056 | + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |
1057 | + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; | |
1058 | + CLANG_WARN_EMPTY_BODY = YES; | |
1059 | + CLANG_WARN_ENUM_CONVERSION = YES; | |
1060 | + CLANG_WARN_INFINITE_RECURSION = YES; | |
1061 | + CLANG_WARN_INT_CONVERSION = YES; | |
1062 | + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |
1063 | + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |
1064 | + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |
1065 | + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |
1066 | + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; | |
1067 | + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |
1068 | + CLANG_WARN_STRICT_PROTOTYPES = YES; | |
1069 | + CLANG_WARN_SUSPICIOUS_MOVE = YES; | |
1070 | + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; | |
1071 | + CLANG_WARN_UNREACHABLE_CODE = YES; | |
1072 | + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |
1073 | + COPY_PHASE_STRIP = NO; | |
1074 | + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; | |
1075 | + ENABLE_NS_ASSERTIONS = NO; | |
1076 | + ENABLE_STRICT_OBJC_MSGSEND = YES; | |
1077 | + ENABLE_USER_SCRIPT_SANDBOXING = YES; | |
1078 | + GCC_C_LANGUAGE_STANDARD = gnu17; | |
1079 | + GCC_NO_COMMON_BLOCKS = YES; | |
1080 | + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |
1081 | + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |
1082 | + GCC_WARN_UNDECLARED_SELECTOR = YES; | |
1083 | + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |
1084 | + GCC_WARN_UNUSED_FUNCTION = YES; | |
1085 | + GCC_WARN_UNUSED_VARIABLE = YES; | |
1086 | + IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |
1087 | + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; | |
1088 | + MTL_ENABLE_DEBUG_INFO = NO; | |
1089 | + MTL_FAST_MATH = YES; | |
1090 | + SDKROOT = iphoneos; | |
1091 | + SWIFT_COMPILATION_MODE = wholemodule; | |
1092 | + VALIDATE_PRODUCT = YES; | |
1093 | + }; | |
1094 | + name = Release; | |
1095 | + }; | |
1096 | + 19FCBF332AC1727900F83A7F /* Debug */ = { | |
1097 | + isa = XCBuildConfiguration; | |
1098 | + buildSettings = { | |
1099 | + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; | |
1100 | + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |
1101 | + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; | |
1102 | + CODE_SIGN_STYLE = Automatic; | |
1103 | + CURRENT_PROJECT_VERSION = 1; | |
1104 | + DEVELOPMENT_TEAM = 6Y97YM76EY; | |
1105 | + GENERATE_INFOPLIST_FILE = YES; | |
1106 | + INFOPLIST_FILE = browser/Info.plist; | |
1107 | + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; | |
1108 | + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; | |
1109 | + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; | |
1110 | + INFOPLIST_KEY_UIUserInterfaceStyle = Light; | |
1111 | + IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |
1112 | + LD_RUNPATH_SEARCH_PATHS = ( | |
1113 | + "$(inherited)", | |
1114 | + "@executable_path/Frameworks", | |
1115 | + ); | |
1116 | + MARKETING_VERSION = 1.0; | |
1117 | + PRODUCT_BUNDLE_IDENTIFIER = "com.4k-soft.browser"; | |
1118 | + PRODUCT_NAME = "$(TARGET_NAME)"; | |
1119 | + SWIFT_EMIT_LOC_STRINGS = YES; | |
1120 | + SWIFT_VERSION = 5.0; | |
1121 | + TARGETED_DEVICE_FAMILY = "1,2"; | |
1122 | + }; | |
1123 | + name = Debug; | |
1124 | + }; | |
1125 | + 19FCBF342AC1727900F83A7F /* Release */ = { | |
1126 | + isa = XCBuildConfiguration; | |
1127 | + buildSettings = { | |
1128 | + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; | |
1129 | + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |
1130 | + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; | |
1131 | + CODE_SIGN_STYLE = Automatic; | |
1132 | + CURRENT_PROJECT_VERSION = 1; | |
1133 | + DEVELOPMENT_TEAM = 6Y97YM76EY; | |
1134 | + GENERATE_INFOPLIST_FILE = YES; | |
1135 | + INFOPLIST_FILE = browser/Info.plist; | |
1136 | + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; | |
1137 | + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; | |
1138 | + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; | |
1139 | + INFOPLIST_KEY_UIUserInterfaceStyle = Light; | |
1140 | + IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |
1141 | + LD_RUNPATH_SEARCH_PATHS = ( | |
1142 | + "$(inherited)", | |
1143 | + "@executable_path/Frameworks", | |
1144 | + ); | |
1145 | + MARKETING_VERSION = 1.0; | |
1146 | + PRODUCT_BUNDLE_IDENTIFIER = "com.4k-soft.browser"; | |
1147 | + PRODUCT_NAME = "$(TARGET_NAME)"; | |
1148 | + SWIFT_EMIT_LOC_STRINGS = YES; | |
1149 | + SWIFT_VERSION = 5.0; | |
1150 | + TARGETED_DEVICE_FAMILY = "1,2"; | |
1151 | + }; | |
1152 | + name = Release; | |
1153 | + }; | |
1154 | +/* End XCBuildConfiguration section */ | |
1155 | + | |
1156 | +/* Begin XCConfigurationList section */ | |
1157 | + 19696AFF2AE80DBD00D1F8F9 /* Build configuration list for PBXNativeTarget "AdBlocker" */ = { | |
1158 | + isa = XCConfigurationList; | |
1159 | + buildConfigurations = ( | |
1160 | + 19696AFD2AE80DBD00D1F8F9 /* Debug */, | |
1161 | + 19696AFE2AE80DBD00D1F8F9 /* Release */, | |
1162 | + ); | |
1163 | + defaultConfigurationIsVisible = 0; | |
1164 | + defaultConfigurationName = Release; | |
1165 | + }; | |
1166 | + 19FCBF192AC1727800F83A7F /* Build configuration list for PBXProject "browser" */ = { | |
1167 | + isa = XCConfigurationList; | |
1168 | + buildConfigurations = ( | |
1169 | + 19FCBF302AC1727900F83A7F /* Debug */, | |
1170 | + 19FCBF312AC1727900F83A7F /* Release */, | |
1171 | + ); | |
1172 | + defaultConfigurationIsVisible = 0; | |
1173 | + defaultConfigurationName = Release; | |
1174 | + }; | |
1175 | + 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "browser" */ = { | |
1176 | + isa = XCConfigurationList; | |
1177 | + buildConfigurations = ( | |
1178 | + 19FCBF332AC1727900F83A7F /* Debug */, | |
1179 | + 19FCBF342AC1727900F83A7F /* Release */, | |
1180 | + ); | |
1181 | + defaultConfigurationIsVisible = 0; | |
1182 | + defaultConfigurationName = Release; | |
1183 | + }; | |
1184 | +/* End XCConfigurationList section */ | |
1185 | + | |
1186 | +/* Begin XCRemoteSwiftPackageReference section */ | |
1187 | + 193B3B842ACAF480002161ED /* XCRemoteSwiftPackageReference "realm-swift" */ = { | |
1188 | + isa = XCRemoteSwiftPackageReference; | |
1189 | + repositoryURL = "https://github.com/realm/realm-swift.git"; | |
1190 | + requirement = { | |
1191 | + branch = master; | |
1192 | + kind = branch; | |
1193 | + }; | |
1194 | + }; | |
1195 | + 199DB1EF2AD3FDEE007E6A81 /* XCRemoteSwiftPackageReference "Alamofire" */ = { | |
1196 | + isa = XCRemoteSwiftPackageReference; | |
1197 | + repositoryURL = "https://github.com/Alamofire/Alamofire.git"; | |
1198 | + requirement = { | |
1199 | + kind = upToNextMajorVersion; | |
1200 | + minimumVersion = 5.8.0; | |
1201 | + }; | |
1202 | + }; | |
1203 | + 19CD89462AC719AB0035CB55 /* XCRemoteSwiftPackageReference "SnapKit" */ = { | |
1204 | + isa = XCRemoteSwiftPackageReference; | |
1205 | + repositoryURL = "https://github.com/SnapKit/SnapKit.git"; | |
1206 | + requirement = { | |
1207 | + kind = upToNextMajorVersion; | |
1208 | + minimumVersion = 5.6.0; | |
1209 | + }; | |
1210 | + }; | |
1211 | +/* End XCRemoteSwiftPackageReference section */ | |
1212 | + | |
1213 | +/* Begin XCSwiftPackageProductDependency section */ | |
1214 | + 193B3B852ACAF480002161ED /* Realm */ = { | |
1215 | + isa = XCSwiftPackageProductDependency; | |
1216 | + package = 193B3B842ACAF480002161ED /* XCRemoteSwiftPackageReference "realm-swift" */; | |
1217 | + productName = Realm; | |
1218 | + }; | |
1219 | + 193B3B872ACAF480002161ED /* RealmSwift */ = { | |
1220 | + isa = XCSwiftPackageProductDependency; | |
1221 | + package = 193B3B842ACAF480002161ED /* XCRemoteSwiftPackageReference "realm-swift" */; | |
1222 | + productName = RealmSwift; | |
1223 | + }; | |
1224 | + 199DB1F02AD3FDEE007E6A81 /* Alamofire */ = { | |
1225 | + isa = XCSwiftPackageProductDependency; | |
1226 | + package = 199DB1EF2AD3FDEE007E6A81 /* XCRemoteSwiftPackageReference "Alamofire" */; | |
1227 | + productName = Alamofire; | |
1228 | + }; | |
1229 | + 19CD89472AC719AC0035CB55 /* SnapKit */ = { | |
1230 | + isa = XCSwiftPackageProductDependency; | |
1231 | + package = 19CD89462AC719AB0035CB55 /* XCRemoteSwiftPackageReference "SnapKit" */; | |
1232 | + productName = SnapKit; | |
1233 | + }; | |
1234 | +/* End XCSwiftPackageProductDependency section */ | |
1235 | + }; | |
1236 | + rootObject = 19FCBF162AC1727800F83A7F /* Project object */; | |
1237 | +} | ... | ... |
1 | +{ | |
2 | + "pins" : [ | |
3 | + { | |
4 | + "identity" : "alamofire", | |
5 | + "kind" : "remoteSourceControl", | |
6 | + "location" : "https://github.com/Alamofire/Alamofire.git", | |
7 | + "state" : { | |
8 | + "revision" : "3dc6a42c7727c49bf26508e29b0a0b35f9c7e1ad", | |
9 | + "version" : "5.8.1" | |
10 | + } | |
11 | + }, | |
12 | + { | |
13 | + "identity" : "realm-core", | |
14 | + "kind" : "remoteSourceControl", | |
15 | + "location" : "https://github.com/realm/realm-core.git", | |
16 | + "state" : { | |
17 | + "revision" : "c569bec4d04da84030d94f376437bc4efda3686b", | |
18 | + "version" : "13.23.1" | |
19 | + } | |
20 | + }, | |
21 | + { | |
22 | + "identity" : "realm-swift", | |
23 | + "kind" : "remoteSourceControl", | |
24 | + "location" : "https://github.com/realm/realm-swift.git", | |
25 | + "state" : { | |
26 | + "branch" : "master", | |
27 | + "revision" : "6b992e508b1fab07d47775f2fd7485fd5f110893" | |
28 | + } | |
29 | + }, | |
30 | + { | |
31 | + "identity" : "snapkit", | |
32 | + "kind" : "remoteSourceControl", | |
33 | + "location" : "https://github.com/SnapKit/SnapKit.git", | |
34 | + "state" : { | |
35 | + "revision" : "f222cbdf325885926566172f6f5f06af95473158", | |
36 | + "version" : "5.6.0" | |
37 | + } | |
38 | + } | |
39 | + ], | |
40 | + "version" : 2 | |
41 | +} | ... | ... |
browser.xcodeproj/project.xcworkspace/xcuserdata/artemtalko.xcuserdatad/Bookmarks/bookmarks.plist
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
3 | +<plist version="1.0"> | |
4 | +<dict> | |
5 | + <key>top-level-items</key> | |
6 | + <array> | |
7 | + <dict> | |
8 | + <key>destination</key> | |
9 | + <dict> | |
10 | + <key>rebasable-url</key> | |
11 | + <dict> | |
12 | + <key>base</key> | |
13 | + <string>workspace</string> | |
14 | + <key>payload</key> | |
15 | + <dict> | |
16 | + <key>relative-path</key> | |
17 | + <string>browser/Modules/History/Controller/HistoryViewController.swift</string> | |
18 | + </dict> | |
19 | + </dict> | |
20 | + <key>type</key> | |
21 | + <string>DVTDocumentLocation</string> | |
22 | + </dict> | |
23 | + <key>type</key> | |
24 | + <string>bookmark</string> | |
25 | + </dict> | |
26 | + </array> | |
27 | +</dict> | |
28 | +</plist> | ... | ... |
No preview for this file type
browser.xcodeproj/project.xcworkspace/xcuserdata/falliot.xcuserdatad/UserInterfaceState.xcuserstate
0 → 100644
No preview for this file type
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<Bucket | |
3 | + uuid = "7D2BF3CE-0152-4175-98D9-E41B0FA9C333" | |
4 | + type = "1" | |
5 | + version = "2.0"> | |
6 | + <Breakpoints> | |
7 | + <BreakpointProxy | |
8 | + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> | |
9 | + <BreakpointContent | |
10 | + uuid = "F889FE98-5ADA-45D9-9094-5319F398E5D0" | |
11 | + shouldBeEnabled = "Yes" | |
12 | + ignoreCount = "0" | |
13 | + continueAfterRunningActions = "No" | |
14 | + filePath = "browser/Models/HistoryToolbarMenuCases.swift" | |
15 | + startingColumnNumber = "9223372036854775807" | |
16 | + endingColumnNumber = "9223372036854775807" | |
17 | + startingLineNumber = "21" | |
18 | + endingLineNumber = "21" | |
19 | + landmarkName = "action" | |
20 | + landmarkType = "24"> | |
21 | + </BreakpointContent> | |
22 | + </BreakpointProxy> | |
23 | + <BreakpointProxy | |
24 | + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> | |
25 | + <BreakpointContent | |
26 | + uuid = "2E2EC010-6906-4B8A-9667-CF365A133EA9" | |
27 | + shouldBeEnabled = "No" | |
28 | + ignoreCount = "0" | |
29 | + continueAfterRunningActions = "No" | |
30 | + filePath = "browser/Modules/SearchResult/View/SearchResultView.swift" | |
31 | + startingColumnNumber = "9223372036854775807" | |
32 | + endingColumnNumber = "9223372036854775807" | |
33 | + startingLineNumber = "20" | |
34 | + endingLineNumber = "20" | |
35 | + landmarkName = "searchResultView" | |
36 | + landmarkType = "24"> | |
37 | + </BreakpointContent> | |
38 | + </BreakpointProxy> | |
39 | + <BreakpointProxy | |
40 | + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> | |
41 | + <BreakpointContent | |
42 | + uuid = "AF29D2F2-0DE8-426B-B8C0-6E69F97CA3CA" | |
43 | + shouldBeEnabled = "No" | |
44 | + ignoreCount = "0" | |
45 | + continueAfterRunningActions = "No" | |
46 | + filePath = "browser/Modules/RemoveAdvert/Controller/RemoveAdvertViewController.swift" | |
47 | + startingColumnNumber = "9223372036854775807" | |
48 | + endingColumnNumber = "9223372036854775807" | |
49 | + startingLineNumber = "82" | |
50 | + endingLineNumber = "82" | |
51 | + landmarkName = "shieldButtonTapped(_:)" | |
52 | + landmarkType = "7"> | |
53 | + </BreakpointContent> | |
54 | + </BreakpointProxy> | |
55 | + <BreakpointProxy | |
56 | + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> | |
57 | + <BreakpointContent | |
58 | + uuid = "2F610807-91FB-4B53-BAE6-77E3D9664161" | |
59 | + shouldBeEnabled = "No" | |
60 | + ignoreCount = "0" | |
61 | + continueAfterRunningActions = "No" | |
62 | + filePath = "browser/Modules/RemoveAdvert/Controller/RemoveAdvertViewController.swift" | |
63 | + startingColumnNumber = "9223372036854775807" | |
64 | + endingColumnNumber = "9223372036854775807" | |
65 | + startingLineNumber = "86" | |
66 | + endingLineNumber = "86" | |
67 | + landmarkName = "shieldButtonTapped(_:)" | |
68 | + landmarkType = "7"> | |
69 | + </BreakpointContent> | |
70 | + </BreakpointProxy> | |
71 | + <BreakpointProxy | |
72 | + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> | |
73 | + <BreakpointContent | |
74 | + uuid = "2DAFEA73-1A5C-412B-9CAB-F119AA59AC98" | |
75 | + shouldBeEnabled = "No" | |
76 | + ignoreCount = "0" | |
77 | + continueAfterRunningActions = "No" | |
78 | + filePath = "browser/Modules/SearchResult/Controller/SearchResultViewController.swift" | |
79 | + startingColumnNumber = "9223372036854775807" | |
80 | + endingColumnNumber = "9223372036854775807" | |
81 | + startingLineNumber = "55" | |
82 | + endingLineNumber = "55" | |
83 | + landmarkName = "setupAdBlocker()" | |
84 | + landmarkType = "7"> | |
85 | + </BreakpointContent> | |
86 | + </BreakpointProxy> | |
87 | + <BreakpointProxy | |
88 | + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> | |
89 | + <BreakpointContent | |
90 | + uuid = "3D9602FE-229B-4486-9E84-86F3385737CB" | |
91 | + shouldBeEnabled = "No" | |
92 | + ignoreCount = "0" | |
93 | + continueAfterRunningActions = "No" | |
94 | + filePath = "browser/Modules/Home/Controller/BrowserHomeViewController.swift" | |
95 | + startingColumnNumber = "9223372036854775807" | |
96 | + endingColumnNumber = "9223372036854775807" | |
97 | + startingLineNumber = "236" | |
98 | + endingLineNumber = "236" | |
99 | + landmarkName = "tabsButtonHandler()" | |
100 | + landmarkType = "7"> | |
101 | + </BreakpointContent> | |
102 | + </BreakpointProxy> | |
103 | + <BreakpointProxy | |
104 | + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> | |
105 | + <BreakpointContent | |
106 | + uuid = "890732EB-28CC-4180-BED8-D29D0A5F9C6A" | |
107 | + shouldBeEnabled = "No" | |
108 | + ignoreCount = "0" | |
109 | + continueAfterRunningActions = "No" | |
110 | + filePath = "browser/Modules/Home/Controller/BrowserHomeViewController.swift" | |
111 | + startingColumnNumber = "9223372036854775807" | |
112 | + endingColumnNumber = "9223372036854775807" | |
113 | + startingLineNumber = "235" | |
114 | + endingLineNumber = "235" | |
115 | + landmarkName = "tabsButtonHandler()" | |
116 | + landmarkType = "7"> | |
117 | + </BreakpointContent> | |
118 | + </BreakpointProxy> | |
119 | + </Breakpoints> | |
120 | +</Bucket> | ... | ... |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
3 | +<plist version="1.0"> | |
4 | +<dict> | |
5 | + <key>SchemeUserState</key> | |
6 | + <dict> | |
7 | + <key>AdBlocker.xcscheme_^#shared#^_</key> | |
8 | + <dict> | |
9 | + <key>orderHint</key> | |
10 | + <integer>0</integer> | |
11 | + </dict> | |
12 | + <key>GettingStarted (Playground) 1.xcscheme</key> | |
13 | + <dict> | |
14 | + <key>isShown</key> | |
15 | + <false/> | |
16 | + <key>orderHint</key> | |
17 | + <integer>5</integer> | |
18 | + </dict> | |
19 | + <key>GettingStarted (Playground) 2.xcscheme</key> | |
20 | + <dict> | |
21 | + <key>isShown</key> | |
22 | + <false/> | |
23 | + <key>orderHint</key> | |
24 | + <integer>6</integer> | |
25 | + </dict> | |
26 | + <key>GettingStarted (Playground).xcscheme</key> | |
27 | + <dict> | |
28 | + <key>isShown</key> | |
29 | + <false/> | |
30 | + <key>orderHint</key> | |
31 | + <integer>2</integer> | |
32 | + </dict> | |
33 | + <key>SnapKitPlayground (Playground) 1.xcscheme</key> | |
34 | + <dict> | |
35 | + <key>isShown</key> | |
36 | + <false/> | |
37 | + <key>orderHint</key> | |
38 | + <integer>3</integer> | |
39 | + </dict> | |
40 | + <key>SnapKitPlayground (Playground) 2.xcscheme</key> | |
41 | + <dict> | |
42 | + <key>isShown</key> | |
43 | + <false/> | |
44 | + <key>orderHint</key> | |
45 | + <integer>4</integer> | |
46 | + </dict> | |
47 | + <key>SnapKitPlayground (Playground) 3.xcscheme</key> | |
48 | + <dict> | |
49 | + <key>isShown</key> | |
50 | + <false/> | |
51 | + <key>orderHint</key> | |
52 | + <integer>0</integer> | |
53 | + </dict> | |
54 | + <key>SnapKitPlayground (Playground) 4.xcscheme</key> | |
55 | + <dict> | |
56 | + <key>isShown</key> | |
57 | + <false/> | |
58 | + <key>orderHint</key> | |
59 | + <integer>5</integer> | |
60 | + </dict> | |
61 | + <key>SnapKitPlayground (Playground) 5.xcscheme</key> | |
62 | + <dict> | |
63 | + <key>isShown</key> | |
64 | + <false/> | |
65 | + <key>orderHint</key> | |
66 | + <integer>6</integer> | |
67 | + </dict> | |
68 | + <key>SnapKitPlayground (Playground).xcscheme</key> | |
69 | + <dict> | |
70 | + <key>isShown</key> | |
71 | + <false/> | |
72 | + <key>orderHint</key> | |
73 | + <integer>1</integer> | |
74 | + </dict> | |
75 | + <key>browser.xcscheme_^#shared#^_</key> | |
76 | + <dict> | |
77 | + <key>orderHint</key> | |
78 | + <integer>1</integer> | |
79 | + </dict> | |
80 | + </dict> | |
81 | +</dict> | |
82 | +</plist> | ... | ... |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
3 | +<plist version="1.0"> | |
4 | +<dict> | |
5 | + <key>SchemeUserState</key> | |
6 | + <dict> | |
7 | + <key>AdBlocker.xcscheme_^#shared#^_</key> | |
8 | + <dict> | |
9 | + <key>orderHint</key> | |
10 | + <integer>1</integer> | |
11 | + </dict> | |
12 | + <key>GettingStarted (Playground) 1.xcscheme</key> | |
13 | + <dict> | |
14 | + <key>isShown</key> | |
15 | + <false/> | |
16 | + <key>orderHint</key> | |
17 | + <integer>6</integer> | |
18 | + </dict> | |
19 | + <key>GettingStarted (Playground) 2.xcscheme</key> | |
20 | + <dict> | |
21 | + <key>isShown</key> | |
22 | + <false/> | |
23 | + <key>orderHint</key> | |
24 | + <integer>7</integer> | |
25 | + </dict> | |
26 | + <key>GettingStarted (Playground).xcscheme</key> | |
27 | + <dict> | |
28 | + <key>isShown</key> | |
29 | + <false/> | |
30 | + <key>orderHint</key> | |
31 | + <integer>5</integer> | |
32 | + </dict> | |
33 | + <key>SnapKitPlayground (Playground) 1.xcscheme</key> | |
34 | + <dict> | |
35 | + <key>isShown</key> | |
36 | + <false/> | |
37 | + <key>orderHint</key> | |
38 | + <integer>3</integer> | |
39 | + </dict> | |
40 | + <key>SnapKitPlayground (Playground) 2.xcscheme</key> | |
41 | + <dict> | |
42 | + <key>isShown</key> | |
43 | + <false/> | |
44 | + <key>orderHint</key> | |
45 | + <integer>4</integer> | |
46 | + </dict> | |
47 | + <key>SnapKitPlayground (Playground).xcscheme</key> | |
48 | + <dict> | |
49 | + <key>isShown</key> | |
50 | + <false/> | |
51 | + <key>orderHint</key> | |
52 | + <integer>2</integer> | |
53 | + </dict> | |
54 | + <key>browser.xcscheme_^#shared#^_</key> | |
55 | + <dict> | |
56 | + <key>orderHint</key> | |
57 | + <integer>0</integer> | |
58 | + </dict> | |
59 | + </dict> | |
60 | +</dict> | |
61 | +</plist> | ... | ... |
browser/.DS_Store
0 → 100644
No preview for this file type
browser/AppDelegate.swift
0 → 100644
1 | +import UIKit | |
2 | + | |
3 | +@main | |
4 | + class AppDelegate: UIResponder, UIApplicationDelegate { | |
5 | + var window: UIWindow? | |
6 | + | |
7 | + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { | |
8 | + | |
9 | + let screenRect = UIScreen.main.bounds | |
10 | + window = UIWindow(frame: screenRect) | |
11 | + | |
12 | + if let window = window { | |
13 | + let navigationViewController = NavigationViewController() | |
14 | + window.rootViewController = navigationViewController | |
15 | + window.makeKeyAndVisible() | |
16 | + } | |
17 | + return true | |
18 | + } | |
19 | +} | ... | ... |
1 | +// Transition.swift | |
2 | +// browser | |
3 | +// | |
4 | +// Created by Artem Talko on 23.11.2023. | |
5 | +// | |
6 | + | |
7 | +import UIKit | |
8 | + | |
9 | + | |
10 | +final class OpenTabsTransition: NSObject, UIViewControllerAnimatedTransitioning { | |
11 | + private var operation: UINavigationController.Operation | |
12 | + | |
13 | + init( operation: UINavigationController.Operation ) { | |
14 | + self.operation = operation | |
15 | + super.init() | |
16 | + } | |
17 | + | |
18 | + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { | |
19 | + return 0.4 | |
20 | + } | |
21 | + | |
22 | + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { | |
23 | + guard let toController = transitionContext.viewController(forKey: .to), | |
24 | + let fromController = transitionContext.viewController(forKey: .from) else { | |
25 | + transitionContext.completeTransition(true) | |
26 | + return | |
27 | + } | |
28 | + switch operation { | |
29 | + case .push : | |
30 | + pushController(fromController: fromController, toController: toController, transitionContext: transitionContext) | |
31 | + case .pop: | |
32 | + popController(fromController: fromController, toController: toController, transitionContext: transitionContext) | |
33 | + case .none: | |
34 | + transitionContext.completeTransition(true) | |
35 | + return | |
36 | + @unknown default: | |
37 | + break | |
38 | + } | |
39 | + } | |
40 | +} | |
41 | + | |
42 | + | |
43 | +//MARK: animation handlers | |
44 | +extension OpenTabsTransition { | |
45 | + private func pushController(fromController: UIViewController, toController: UIViewController, transitionContext: UIViewControllerContextTransitioning) { | |
46 | + let container = transitionContext.containerView | |
47 | + guard let tabsController = fromController as? TabsViewController else { | |
48 | + transitionContext.completeTransition(true) | |
49 | + return | |
50 | + } | |
51 | + guard let browserHomeController = toController as? BrowserHomeViewController else { | |
52 | + transitionContext.completeTransition(true) | |
53 | + return | |
54 | + } | |
55 | + let cellIndexPathForTransition = tabsController.getCellIndex() | |
56 | + | |
57 | + container.insertSubview(browserHomeController.mainView, at: 0) | |
58 | + DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) { | |
59 | + let tabsCollectionView = tabsController.mainView.openedTabsCollectionView | |
60 | + tabsCollectionView.scrollToItem(at: cellIndexPathForTransition, at: .bottom, animated: false) | |
61 | + DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) { | |
62 | + let cell = tabsController.mainView.openedTabsCollectionView.cellForItem(at: cellIndexPathForTransition) | |
63 | + let browserHomeImage = UIImageView() | |
64 | + browserHomeImage.image = SnapshotService.shared.makeSnapshot(browserHomeController.mainView) | |
65 | + | |
66 | + guard let lastTab = cell as? OpenedTabsCollectionViewCell else { | |
67 | + return | |
68 | + } | |
69 | + lastTab.isHidden = true | |
70 | + | |
71 | + container.addSubview(browserHomeImage) | |
72 | + browserHomeImage.frame = lastTab.frame | |
73 | + UIView.animate(withDuration: 0.2) { | |
74 | + browserHomeImage.frame = UIScreen.main.bounds | |
75 | + } completion: { _ in | |
76 | + browserHomeImage.removeFromSuperview() | |
77 | + lastTab.isHidden = false | |
78 | + transitionContext.completeTransition(true) | |
79 | + } | |
80 | + } | |
81 | + } | |
82 | + } | |
83 | + | |
84 | + private func popController(fromController: UIViewController, toController: UIViewController, transitionContext: UIViewControllerContextTransitioning) { | |
85 | + let container = transitionContext.containerView | |
86 | + guard let tabsController = toController as? TabsViewController else { | |
87 | + transitionContext.completeTransition(true) | |
88 | + return | |
89 | + } | |
90 | + guard let browserHomeController = fromController as? BrowserHomeViewController else { | |
91 | + transitionContext.completeTransition(true) | |
92 | + return | |
93 | + } | |
94 | + let cellIndexPathForTransition = tabsController.getCellIndex() | |
95 | + | |
96 | + container.insertSubview(tabsController.mainView, at: 0) | |
97 | + DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) { | |
98 | + let tabsCollectionView = tabsController.mainView.openedTabsCollectionView | |
99 | + tabsCollectionView.scrollToItem(at: cellIndexPathForTransition, at: .bottom, animated: false) | |
100 | + let lastItemIndex = tabsController.getCellIndex() | |
101 | + | |
102 | + DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) { | |
103 | + let cell = tabsController.mainView.openedTabsCollectionView.cellForItem(at: lastItemIndex) | |
104 | + let browserHomeImage = UIImageView() | |
105 | + browserHomeImage.image = SnapshotService.shared.makeSnapshot(browserHomeController.mainView) | |
106 | + | |
107 | + guard let lastTab = cell as? OpenedTabsCollectionViewCell else { | |
108 | + return | |
109 | + } | |
110 | + lastTab.isHidden = true | |
111 | + | |
112 | + container.addSubview(browserHomeImage) | |
113 | + browserHomeImage.frame = browserHomeController.mainView.frame | |
114 | + UIView.animate(withDuration: 0.2) { | |
115 | + fromController.view.isHidden = true | |
116 | + browserHomeImage.frame = lastTab.convertFrameToScreenCoordinates() ?? CGRect() | |
117 | + } completion: { _ in | |
118 | + browserHomeImage.removeFromSuperview() | |
119 | + lastTab.isHidden = false | |
120 | + transitionContext.completeTransition(true) | |
121 | + } | |
122 | + } | |
123 | + } | |
124 | + } | |
125 | +} | |
126 | + | ... | ... |
browser/DataBases/BrowserTabDataBase.swift
0 → 100644
1 | +// | |
2 | +// BrowserTab.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 02.10.2023. | |
6 | +// | |
7 | + | |
8 | + | |
9 | +import UIKit | |
10 | +import Realm | |
11 | +import RealmSwift | |
12 | + | |
13 | +class BrowserTabDataBase: Object { | |
14 | + @Persisted(primaryKey: true) var tabId: String = UUID().uuidString | |
15 | + @Persisted var tabTitle: String | |
16 | + @Persisted var TabUrl: String | |
17 | + @Persisted var snapshotImageData: Data? | |
18 | + | |
19 | + convenience init(tabTitle: String, snapshotImage: UIImage?, tabUrl: String) { | |
20 | + self.init() | |
21 | + self.tabTitle = tabTitle | |
22 | + self.TabUrl = tabUrl | |
23 | + if let image = snapshotImage { | |
24 | + self.snapshotImageData = image.pngData() | |
25 | + } | |
26 | + } | |
27 | +} | ... | ... |
browser/DataBases/HistoryDataBase.swift
0 → 100644
1 | +// | |
2 | +// HistoryDataBase.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 16.10.2023. | |
6 | +// | |
7 | + | |
8 | + | |
9 | +import UIKit | |
10 | +import Realm | |
11 | +import RealmSwift | |
12 | + | |
13 | +class HistoryDataBase: Object { | |
14 | + @Persisted(primaryKey: true) var historyCellId: String = UUID().uuidString | |
15 | + @Persisted var siteTitle: String | |
16 | + @Persisted var siteUrl: String | |
17 | + @Persisted var lastVisit: Date | |
18 | + | |
19 | + convenience init(siteTitle: String, siteUrl: String, lastVisit: Date) { | |
20 | + self.init() | |
21 | + self.siteTitle = siteTitle | |
22 | + self.siteUrl = siteUrl | |
23 | + self.lastVisit = lastVisit | |
24 | + } | |
25 | +} | |
26 | + | ... | ... |
browser/Extentions/BinaryFloatingPoint.swift
0 → 100644
1 | +// | |
2 | +// File.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 27.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | + | |
11 | +extension BinaryFloatingPoint { | |
12 | + private var size: CGSize { | |
13 | + return CGSize(width: 375, height: 812) | |
14 | + } | |
15 | + | |
16 | + var sizeW: CGFloat { | |
17 | + (CGFloat(self) * UIScreen.main.bounds.width / size.width) | |
18 | + } | |
19 | + | |
20 | + var sizeH: CGFloat { | |
21 | + (CGFloat(self) * UIScreen.main.bounds.height / size.height) | |
22 | + } | |
23 | + | |
24 | + var lessThanOrEqualToSizeW: CGFloat { | |
25 | + UIScreen.main.bounds.width < size.width ? self.sizeW : CGFloat(self) | |
26 | + } | |
27 | + | |
28 | + var lessThanOrEqualToSizeH: CGFloat { | |
29 | + UIScreen.main.bounds.height < size.height ? self.sizeH : CGFloat(self) | |
30 | + } | |
31 | +} | |
32 | + | |
33 | +extension BinaryInteger { | |
34 | + var sizeW: CGFloat { | |
35 | + CGFloat(self).sizeW | |
36 | + } | |
37 | + | |
38 | + var sizeH: CGFloat { | |
39 | + CGFloat(self).sizeH | |
40 | + } | |
41 | + | |
42 | + var lessThanOrEqualToSizeW: CGFloat { | |
43 | + CGFloat(self).lessThanOrEqualToSizeW | |
44 | + } | |
45 | + | |
46 | + var lessThanOrEqualToSizeH: CGFloat { | |
47 | + CGFloat(self).lessThanOrEqualToSizeH | |
48 | + } | |
49 | +} | ... | ... |
1 | +// | |
2 | +// UIView+convertFrameToScreenCoordinates.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 30.10.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +extension UICollectionViewCell { | |
11 | + func convertFrameToScreenCoordinates() -> CGRect? { | |
12 | + guard let rootView = UIApplication.shared.keyWindow?.rootViewController?.view else { | |
13 | + return nil | |
14 | + } | |
15 | + | |
16 | + let convertedOrigin = convert(bounds.origin, to: rootView) | |
17 | + return CGRect(origin: convertedOrigin, size: bounds.size) | |
18 | + } | |
19 | + | |
20 | + func convertRectToFullScreen(_ rect: CGRect) -> CGRect? { | |
21 | + guard let window = UIApplication.shared.windows.first else { | |
22 | + return nil | |
23 | + } | |
24 | + | |
25 | + let rectInWindow = convert(rect, to: window) | |
26 | + let fullScreenRect = window.convert(rectInWindow, to: UIScreen.main.coordinateSpace) | |
27 | + | |
28 | + return fullScreenRect | |
29 | + } | |
30 | +} | ... | ... |
browser/Info.plist
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
3 | +<plist version="1.0"> | |
4 | +<dict> | |
5 | + <key>NSAppTransportSecurity</key> | |
6 | + <dict> | |
7 | + <key>NSAllowsArbitraryLoads</key> | |
8 | + <true/> | |
9 | + <key>NSAllowsArbitraryLoadsForMedia</key> | |
10 | + <true/> | |
11 | + </dict> | |
12 | + <key>UIAppFonts</key> | |
13 | + <array> | |
14 | + <string>FontsFree-Net-SFProText-Semibold.ttf</string> | |
15 | + <string>FontsFree-Net-SFProText-Regular.ttf</string> | |
16 | + </array> | |
17 | +</dict> | |
18 | +</plist> | ... | ... |
browser/Managers/CachingManager.swift
0 → 100644
1 | +// | |
2 | +// FirstTimeOpen.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 27.09.2023. | |
6 | +// | |
7 | + | |
8 | +import Foundation | |
9 | + | |
10 | +final class CachingManager { | |
11 | + private enum Keys { | |
12 | + static let isFirstAppLoad = "IsFirstAppLoad" | |
13 | + static let isAdBlocking = "IsAdBlocking" | |
14 | + } | |
15 | + | |
16 | + static let shared = CachingManager() | |
17 | + private let userDefaults = UserDefaults.standard | |
18 | + | |
19 | + var isFirstAppLoad: Bool { | |
20 | + get { return userDefaults.bool(forKey: Keys.isFirstAppLoad) } | |
21 | + set { userDefaults.set(newValue, forKey: Keys.isFirstAppLoad) } | |
22 | + } | |
23 | + var isAdBlocking: Bool { | |
24 | + get { return userDefaults.bool(forKey: Keys.isAdBlocking) } | |
25 | + set { userDefaults.set(newValue, forKey: Keys.isAdBlocking) } | |
26 | + } | |
27 | +} | ... | ... |
browser/Managers/DateManager.swift
0 → 100644
1 | +// | |
2 | +// DateManager.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 17.10.2023. | |
6 | +// | |
7 | + | |
8 | +import Foundation | |
9 | + | |
10 | + | |
11 | +final class DateManager { | |
12 | + static let shared = DateManager() | |
13 | + | |
14 | + func getTimeFromDB(_ date: Date?) -> String { | |
15 | + let timeFormatter = DateFormatter() | |
16 | + timeFormatter.dateFormat = "h:mm a" | |
17 | + return timeFormatter.string(from: date ?? Date()) | |
18 | + } | |
19 | + | |
20 | + var dateFormatter: DateFormatter{ | |
21 | + let obj = DateFormatter() | |
22 | + obj.dateFormat = "EEEE, d MMM" | |
23 | + return obj | |
24 | + } | |
25 | + | |
26 | + var currentDate: Date { | |
27 | + let obj = Date() | |
28 | + return obj | |
29 | + } | |
30 | +} | |
31 | + | |
32 | + | |
33 | + | ... | ... |
browser/Managers/HistoryDBManager.swift
0 → 100644
1 | +// | |
2 | +// HistoryDBManager.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 17.10.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import Realm | |
10 | +import RealmSwift | |
11 | + | |
12 | +class HistoryDBManager { | |
13 | + static let shared = HistoryDBManager() | |
14 | + private let realm: Realm | |
15 | + | |
16 | + | |
17 | + | |
18 | + private init() { | |
19 | + do { | |
20 | + self.realm = try Realm() | |
21 | + } catch { | |
22 | + fatalError("Error initializing Realm: \(error.localizedDescription)") | |
23 | + } | |
24 | + } | |
25 | + | |
26 | + //MARK: ADDING | |
27 | + func saveToHistory(siteTitle: String, siteUrl: String, lastVisit: Date) { | |
28 | + let historyCell = HistoryDataBase(siteTitle: siteTitle, siteUrl: siteUrl, lastVisit: lastVisit) | |
29 | + do { | |
30 | + try realm.write { | |
31 | + realm.add(historyCell) | |
32 | + } | |
33 | + | |
34 | + } catch { | |
35 | + print("Error adding new tab: \(error.localizedDescription)") | |
36 | + } | |
37 | + } | |
38 | + | |
39 | + //MARK: GETTING | |
40 | + func getHistory(sorted: Bool = false) -> [HistoryDataBase] { | |
41 | + if sorted { | |
42 | + let history = realm.objects(HistoryDataBase.self).sorted(byKeyPath: "lastVisit", ascending: false) | |
43 | + return Array(history) | |
44 | + } else { | |
45 | + let history = realm.objects(HistoryDataBase.self) | |
46 | + return Array(history) | |
47 | + } | |
48 | + } | |
49 | + | |
50 | + func getHistoryDataForTableView() -> ([HistoryElement]) { | |
51 | + let stories = getHistory(sorted: true) | |
52 | + return createHistoryData(elements: Array(stories)) | |
53 | + } | |
54 | + | |
55 | + func createHistoryData(elements: [HistoryDataBase]) -> ([HistoryElement]) { | |
56 | + var groupedData: [String: [HistoryDataBase]] = [:] | |
57 | + let dateFormatter = DateManager.shared.dateFormatter | |
58 | + | |
59 | + for data in elements { | |
60 | + let formattedDate = dateFormatter.string(from: data.lastVisit) | |
61 | + if groupedData[formattedDate] == nil { | |
62 | + groupedData[formattedDate] = [] | |
63 | + } | |
64 | + groupedData[formattedDate]?.append(data) | |
65 | + } | |
66 | + | |
67 | + let result = groupedData.map({ HistoryElement( name: $0.key, stories: $0.value )}) | |
68 | + | |
69 | + return result | |
70 | + } | |
71 | + | |
72 | + func getFilteredHistory(filter: String) -> ([HistoryElement]) { | |
73 | + let lowercasedFilter = filter.lowercased() | |
74 | + let history = getHistory(sorted: true) | |
75 | + let filteredHistory = history.filter({ $0.siteTitle.lowercased().contains(lowercasedFilter) || $0.siteUrl.lowercased().contains(lowercasedFilter)}) | |
76 | + return createHistoryData(elements: filteredHistory) | |
77 | + } | |
78 | + | |
79 | + //MARK: DELETING | |
80 | + func cleanHistory() { | |
81 | + do { | |
82 | + let history = realm.objects(HistoryDataBase.self) | |
83 | + try realm.write { | |
84 | + realm.delete(history) | |
85 | + } | |
86 | + | |
87 | + } catch { | |
88 | + print("Error cleaning history: \(error.localizedDescription)") | |
89 | + } | |
90 | + } | |
91 | + | |
92 | + func deleteHistoryInRange(startDate: Date) { | |
93 | + do { | |
94 | + let history = realm.objects(HistoryDataBase.self).filter("lastVisit >= %@", startDate) | |
95 | + try realm.write { | |
96 | + realm.delete(history) | |
97 | + } | |
98 | + | |
99 | + } catch { | |
100 | + print("Error deleting history within the specified time range: \(error.localizedDescription)") | |
101 | + } | |
102 | + } | |
103 | + | |
104 | + func deleteHistoryCell(tabId: String) { | |
105 | + if let historyCellToDelete = realm.object(ofType: HistoryDataBase.self, forPrimaryKey: tabId) { | |
106 | + do { | |
107 | + try realm.write { | |
108 | + realm.delete(historyCellToDelete) | |
109 | + } | |
110 | + | |
111 | + } catch { | |
112 | + print("Error deleting history cell: \(error.localizedDescription)") | |
113 | + } | |
114 | + } | |
115 | + } | |
116 | + | |
117 | + | |
118 | +} | |
119 | + | ... | ... |
browser/Managers/TabManager.swift
0 → 100644
1 | +// | |
2 | +// DataBaseManager.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 02.10.2023. | |
6 | +// | |
7 | + | |
8 | +import Realm | |
9 | +import RealmSwift | |
10 | +import Alamofire | |
11 | +import UIKit | |
12 | + | |
13 | +final class TabManager { | |
14 | + static let shared = TabManager() | |
15 | + private let realm: Realm | |
16 | + | |
17 | + | |
18 | + private init() { | |
19 | + do { | |
20 | + self.realm = try Realm() | |
21 | + } catch { | |
22 | + fatalError("Error initializing Realm: \(error.localizedDescription)") | |
23 | + } | |
24 | + } | |
25 | + | |
26 | + | |
27 | + func saveTabWithComplition(tabTitle: String, snapshotImage: UIImage?, tabUrl: String, completion: (Result<Void,Error>) -> Void) { | |
28 | + let newTab = BrowserTabDataBase(tabTitle: tabTitle, snapshotImage: snapshotImage, tabUrl: tabUrl) | |
29 | + | |
30 | + do { | |
31 | + try realm.write { | |
32 | + realm.add(newTab) | |
33 | + completion(.success(())) | |
34 | + } | |
35 | + } catch { | |
36 | + print("Error adding new tab: \(error.localizedDescription)") | |
37 | + completion(.failure(error)) | |
38 | + } | |
39 | + } | |
40 | + | |
41 | + func saveTab(tabTitle: String, snapshotImage: UIImage?, tabUrl: String) { | |
42 | + let newTab = BrowserTabDataBase(tabTitle: tabTitle, snapshotImage: snapshotImage, tabUrl: tabUrl) | |
43 | + | |
44 | + do { | |
45 | + try realm.write { | |
46 | + realm.add(newTab) | |
47 | + } | |
48 | + } catch { | |
49 | + print("Error adding new tab: \(error.localizedDescription)") | |
50 | + } | |
51 | + } | |
52 | + | |
53 | + func updateTab(tabId: String, newTabTitle: String, newSnapshotImage: UIImage?, newTabUrl: String, completion: (Result<Void, Error>) -> Void) { | |
54 | + if let tabToUpdate = realm.object(ofType: BrowserTabDataBase.self, forPrimaryKey: tabId) { | |
55 | + do { | |
56 | + try realm.write { | |
57 | + tabToUpdate.tabTitle = newTabTitle | |
58 | + tabToUpdate.TabUrl = newTabUrl | |
59 | + if let image = newSnapshotImage { | |
60 | + tabToUpdate.snapshotImageData = image.pngData() | |
61 | + } | |
62 | + completion(.success(())) | |
63 | + } | |
64 | + } catch { | |
65 | + print("Error updating tab: \(error.localizedDescription)") | |
66 | + completion(.failure(error)) | |
67 | + } | |
68 | + } else { | |
69 | + let error = NSError(domain: "Error", code: 404, userInfo: [NSLocalizedDescriptionKey: "Tab not found"]) | |
70 | + completion(.failure(error)) | |
71 | + } | |
72 | + } | |
73 | + | |
74 | + func getAllTabs() -> [BrowserTabDataBase] { | |
75 | + let savedTabs = realm.objects(BrowserTabDataBase.self) | |
76 | + return Array(savedTabs) | |
77 | + } | |
78 | + | |
79 | + func deleteTab(tabId: String) { | |
80 | + if let tabToDelete = realm.object(ofType: BrowserTabDataBase.self, forPrimaryKey: tabId) { | |
81 | + do { | |
82 | + try realm.write { | |
83 | + realm.delete(tabToDelete) | |
84 | + } | |
85 | + } catch { | |
86 | + print("Error deleting tab: \(error.localizedDescription)") | |
87 | + } | |
88 | + } | |
89 | + } | |
90 | +} | |
91 | + | ... | ... |
browser/Models/HistoryElement.swift
0 → 100644
browser/Models/HistoryToolbarMenuCases.swift
0 → 100644
1 | +// | |
2 | +// HistoryToolbar.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 14.11.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +enum menuCases: CaseIterable { | |
11 | + case allTime | |
12 | + case lastMonth | |
13 | + case todayAndYesterday | |
14 | + case today | |
15 | + case lastHour | |
16 | + //MARK: todo | |
17 | + var action: UIAction { | |
18 | + switch self { | |
19 | + case .allTime: | |
20 | + return UIAction(title: "All time") { _ in | |
21 | + HistoryDBManager.shared.cleanHistory() | |
22 | + | |
23 | + } | |
24 | + case .lastMonth: | |
25 | + return UIAction(title: "The last 30 days") { _ in | |
26 | + let lastMonth = Calendar.current.date(byAdding: .day, value: -30, to: Date()) ?? Date() | |
27 | + HistoryDBManager.shared.deleteHistoryInRange(startDate: lastMonth) | |
28 | + } | |
29 | + case .todayAndYesterday: | |
30 | + return UIAction(title: "Today and yesterday") { _ in | |
31 | + let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date()) ?? Date() | |
32 | + HistoryDBManager.shared.deleteHistoryInRange(startDate: yesterday) | |
33 | + } | |
34 | + case .today: | |
35 | + return UIAction(title: "Today") { _ in | |
36 | + let startOfToday = Calendar.current.startOfDay(for: Date()) | |
37 | + HistoryDBManager.shared.deleteHistoryInRange(startDate: startOfToday) | |
38 | + } | |
39 | + case .lastHour: | |
40 | + return UIAction(title: "The last hour") { _ in | |
41 | + let lastHour = Calendar.current.date(byAdding: .hour, value: -1, to: Date()) ?? Date() | |
42 | + HistoryDBManager.shared.deleteHistoryInRange(startDate: lastHour) | |
43 | + } | |
44 | + } | |
45 | + } | |
46 | +} | ... | ... |
1 | +// | |
2 | +// HistoryViewController.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 29.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import RealmSwift | |
10 | + | |
11 | +final class HistoryViewController: UIViewController { | |
12 | + private let mainView = HistoryView() | |
13 | + | |
14 | + private var objectNotificationToken: NotificationToken? | |
15 | + | |
16 | + private var historyData: [HistoryElement] = [] { | |
17 | + didSet { | |
18 | + filteredData = historyData | |
19 | + } | |
20 | + } | |
21 | + private var filteredData: [HistoryElement] = [] { | |
22 | + didSet { | |
23 | + mainView.historyTabsTableView.reloadData() | |
24 | + } | |
25 | + } | |
26 | + | |
27 | + override func viewWillAppear(_ animated: Bool) { | |
28 | + super.viewWillAppear(animated) | |
29 | + navigationController?.isNavigationBarHidden = false | |
30 | + navigationItem.title = "History" | |
31 | + } | |
32 | + | |
33 | + override func viewDidLoad() { | |
34 | + super.viewDidLoad() | |
35 | + initViewController() | |
36 | + } | |
37 | + | |
38 | + private func initViewController() { | |
39 | + setupTableView() | |
40 | + addTargets() | |
41 | + setupSearchBar() | |
42 | + historyData = HistoryDBManager.shared.getHistoryDataForTableView() | |
43 | + historyChangesObserve() | |
44 | + } | |
45 | + | |
46 | + override func loadView() { | |
47 | + view = mainView | |
48 | + view.backgroundColor = .white | |
49 | + navigationController?.isNavigationBarHidden = false | |
50 | + navigationItem.title = "History" | |
51 | + // historyChangesObserve() | |
52 | + } | |
53 | + | |
54 | + init() { | |
55 | + super.init(nibName: nil, bundle: nil) | |
56 | + } | |
57 | + | |
58 | + required init?(coder: NSCoder) { | |
59 | + fatalError("init(coder:) has not been implemented") | |
60 | + } | |
61 | +} | |
62 | + | |
63 | +//MARK: - TableView Extention | |
64 | +extension HistoryViewController: UITableViewDelegate, UITableViewDataSource { | |
65 | + | |
66 | + func numberOfSections(in tableView: UITableView) -> Int { | |
67 | + return filteredData.count | |
68 | + } | |
69 | + | |
70 | + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { | |
71 | + return filteredData[section].name | |
72 | + } | |
73 | + | |
74 | + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
75 | + return filteredData[section].stories.count | |
76 | + } | |
77 | + | |
78 | + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
79 | + guard let cell = tableView.dequeueReusableCell(withIdentifier: "HistoryTableViewCell", for: indexPath) as? HistoryTableViewCell else { | |
80 | + return HistoryTableViewCell() | |
81 | + } | |
82 | + let row = indexPath.row | |
83 | + let section = indexPath.section | |
84 | + | |
85 | + cell.model = filteredData[section].stories[row] | |
86 | + | |
87 | + return cell | |
88 | + } | |
89 | + | |
90 | + private func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { | |
91 | + return true | |
92 | + } | |
93 | + | |
94 | + func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { | |
95 | + if (editingStyle == .delete) { | |
96 | + let row = indexPath.row | |
97 | + let section = indexPath.section | |
98 | + let historyCellData = filteredData[section].stories[row] | |
99 | + let tabId = historyCellData.historyCellId | |
100 | + HistoryDBManager.shared.deleteHistoryCell(tabId: tabId) | |
101 | + filteredData[section].stories.remove(at: row) | |
102 | + mainView.historyTabsTableView.reloadData() | |
103 | + } | |
104 | + } | |
105 | + | |
106 | + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | |
107 | + let section = indexPath.section | |
108 | + let index = indexPath.row | |
109 | + let urlForFunc = historyData[section].stories[index].siteUrl | |
110 | + if let navigationController = presentingViewController as? NavigationViewController { | |
111 | + for viewController in navigationController.viewControllers { | |
112 | + if let browserHomeViewController = viewController as? BrowserHomeViewController { | |
113 | + browserHomeViewController.urlManagment(urlForFunc) | |
114 | + } | |
115 | + } | |
116 | + dismiss(animated: true) | |
117 | + } | |
118 | + } | |
119 | + | |
120 | + func setupTableView() { | |
121 | + mainView.historyTabsTableView.dataSource = self | |
122 | + mainView.historyTabsTableView.delegate = self | |
123 | + mainView.historyTabsTableView.register(HistoryTableViewCell.self, forCellReuseIdentifier: StringConstants.historyTableViewCell) | |
124 | + } | |
125 | +} | |
126 | + | |
127 | + | |
128 | + | |
129 | +//MARK: Helper | |
130 | +extension HistoryViewController { | |
131 | + private func addTargets() { | |
132 | + mainView.historySearchBar.searchTextFieldView.addTarget(self, action: #selector(searchBarTextChanged), for: .editingChanged) | |
133 | + addToolbarTargets() | |
134 | + } | |
135 | + | |
136 | + private func addToolbarTargets() { | |
137 | + mainView.historyToolbarView.action = didTabButtonTapped | |
138 | + } | |
139 | +} | |
140 | + | |
141 | + | |
142 | +//MARK: Targets | |
143 | +extension HistoryViewController { | |
144 | + func didTabButtonTapped(type: historyToolbarElementType) { | |
145 | + if type == .clean { | |
146 | + HistoryDBManager.shared.cleanHistory() | |
147 | + historyData.removeAll() | |
148 | + mainView.historyTabsTableView.reloadData() | |
149 | + } | |
150 | + } | |
151 | +} | |
152 | + | |
153 | + | |
154 | +//MARK: Action | |
155 | +extension HistoryViewController { | |
156 | + @objc | |
157 | + private func searchResultAction() { | |
158 | + mainView.historySearchBar.searchTextFieldView.text = nil | |
159 | + filteredData = historyData | |
160 | + } | |
161 | + | |
162 | + @objc private func searchBarTextChanged() { | |
163 | + if let text = mainView.historySearchBar.searchTextFieldView.text { | |
164 | + if text.isEmpty { | |
165 | + filteredData = historyData | |
166 | + } else { | |
167 | + filteredData = HistoryDBManager.shared.getFilteredHistory(filter: text) | |
168 | + } | |
169 | + } | |
170 | + } | |
171 | +} | |
172 | + | |
173 | + | |
174 | +//MARK: SearchBar | |
175 | +extension HistoryViewController: UITextFieldDelegate { | |
176 | + func textFieldDidBeginEditing(_ textField: UITextField) { | |
177 | + mainView.historySearchBar.searchTextFieldView.text = nil | |
178 | + mainView.historySearchBar.searchTextFieldView.textColor = .black | |
179 | + } | |
180 | + | |
181 | + func setupSearchBar() { | |
182 | + mainView.historySearchBar.searchTextFieldView.delegate = self | |
183 | + } | |
184 | +} | |
185 | + | |
186 | +//MARK: History DB observe | |
187 | +extension HistoryViewController { | |
188 | + func historyChangesObserve() { | |
189 | + let historyObjects = HistoryDBManager.shared.getHistory() | |
190 | + for historyObject in historyObjects { | |
191 | + objectNotificationToken = historyObject.observe { [self] changes in | |
192 | + switch changes { | |
193 | + case .error(let error): | |
194 | + print("Error observing changes in Realm: \(error)") | |
195 | + case .change(_, _): | |
196 | + break | |
197 | + case .deleted: | |
198 | + print("Object deleted in Realm") | |
199 | + self.historyData = HistoryDBManager.shared.getHistoryDataForTableView() | |
200 | + self.mainView.historyTabsTableView.reloadData() | |
201 | + } | |
202 | + } | |
203 | + } | |
204 | + } | |
205 | +} | ... | ... |
1 | +// | |
2 | +// HistoryTableViewCell.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 29.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import SnapKit | |
10 | + | |
11 | +class HistoryTableViewCell: UITableViewCell { | |
12 | + var model: HistoryDataBase? { | |
13 | + didSet { | |
14 | + handleUI() | |
15 | + } | |
16 | + } | |
17 | + | |
18 | + let searchImageLogo: UIImageView = { | |
19 | + let obj = UIImageView() | |
20 | + obj.image = UIImage(systemName: "magnifyingglass") | |
21 | + obj.tintColor = .gray | |
22 | + obj.contentMode = .scaleAspectFit | |
23 | + return obj | |
24 | + }() | |
25 | + | |
26 | + let lastVisitSiteLabel: UILabel = { | |
27 | + let obj = UILabel() | |
28 | + obj.font = FontConstants.regularFont_14 | |
29 | + return obj | |
30 | + }() | |
31 | + | |
32 | + let lastVisitSiteUrlLabel: UILabel = { | |
33 | + let obj = UILabel() | |
34 | + obj.textColor = .gray | |
35 | + obj.font = FontConstants.regularFont_12 | |
36 | + return obj | |
37 | + }() | |
38 | + | |
39 | + let lastVisitDateLabel: UILabel = { | |
40 | + let obj = UILabel() | |
41 | + obj.font = FontConstants.regularFont_12 | |
42 | + obj.textColor = .gray | |
43 | + return obj | |
44 | + }() | |
45 | + | |
46 | + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { | |
47 | + super.init(style: style, reuseIdentifier: reuseIdentifier) | |
48 | + setup() | |
49 | + } | |
50 | + | |
51 | + required init?(coder: NSCoder) { | |
52 | + fatalError("init(coder:) has not been implemented") | |
53 | + } | |
54 | + | |
55 | + private func setup() { | |
56 | + contentView.addSubview(searchImageLogo) | |
57 | + contentView.addSubview(lastVisitSiteLabel) | |
58 | + contentView.addSubview(lastVisitSiteUrlLabel) | |
59 | + contentView.addSubview(lastVisitDateLabel) | |
60 | + setupConstraints() | |
61 | + } | |
62 | + | |
63 | + private func setupConstraints() { | |
64 | + searchImageLogo.snp.makeConstraints { make in | |
65 | + make.leading.equalToSuperview().inset(8.sizeW) | |
66 | + make.top.equalToSuperview().inset(8.sizeH) | |
67 | + make.height.equalTo(18.sizeW) | |
68 | + make.width.equalTo(18.sizeW) | |
69 | + } | |
70 | + lastVisitSiteLabel.snp.makeConstraints { make in | |
71 | + make.leading.equalTo(searchImageLogo.snp.trailing).offset(8.sizeW) | |
72 | + make.trailing.equalTo(lastVisitDateLabel.snp.leading).offset(-8.sizeW) | |
73 | + make.top.equalToSuperview().inset(8.sizeH) | |
74 | + } | |
75 | + lastVisitDateLabel.snp.makeConstraints { make in | |
76 | + make.trailing.equalToSuperview().inset(8.sizeW) | |
77 | + make.top.equalToSuperview().inset(8.sizeH) | |
78 | + } | |
79 | + lastVisitSiteUrlLabel.snp.makeConstraints { make in | |
80 | + make.leading.equalToSuperview().offset(34.sizeW) | |
81 | + make.top.equalTo(lastVisitSiteLabel.snp.bottom).offset(4.sizeH) | |
82 | + make.bottom.equalToSuperview().inset(8.sizeH) | |
83 | + make.trailing.equalToSuperview().inset(61.sizeW) | |
84 | + } | |
85 | + } | |
86 | +} | |
87 | + | |
88 | +extension HistoryTableViewCell { | |
89 | + private func handleUI() { | |
90 | + let dateForLabel = DateManager.shared.getTimeFromDB(model?.lastVisit) | |
91 | + lastVisitDateLabel.text = dateForLabel | |
92 | + lastVisitSiteLabel.text = model?.siteTitle | |
93 | + lastVisitSiteUrlLabel.text = model?.siteUrl | |
94 | + } | |
95 | +} | |
96 | + | ... | ... |
1 | +// | |
2 | +// HistorySearchBarView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 01.10.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class HistorySearchBarView: UIView { | |
11 | + let searchImageView: UIImageView = { | |
12 | + let obj = UIImageView() | |
13 | + let magnifyImage = UIImage(systemName: "magnifyingglass")?.withTintColor(.gray, renderingMode: .alwaysOriginal) | |
14 | + obj.image = magnifyImage | |
15 | + obj.contentMode = .scaleAspectFit | |
16 | + return obj | |
17 | + }() | |
18 | + | |
19 | + let searchTextFieldView: UITextField = { | |
20 | + let obj = UITextField() | |
21 | + obj.text = StringConstants.search | |
22 | + obj.textColor = ColorConstants.gray | |
23 | + return obj | |
24 | + }() | |
25 | + | |
26 | + override init(frame: CGRect) { | |
27 | + super.init(frame: frame) | |
28 | + setup() | |
29 | + setupConstraints() | |
30 | + } | |
31 | + | |
32 | + required init?(coder: NSCoder) { | |
33 | + fatalError("init(coder:) has not been implemented") | |
34 | + } | |
35 | + | |
36 | + private func setup() { | |
37 | + addSubview(searchImageView) | |
38 | + addSubview(searchTextFieldView) | |
39 | + } | |
40 | + | |
41 | + private func setupConstraints() { | |
42 | + searchImageView.snp.makeConstraints { make in | |
43 | + make.leading.equalToSuperview().offset(16.sizeW) | |
44 | + make.top.bottom.equalToSuperview().inset(8.sizeH) | |
45 | + make.height.equalTo(16.sizeH) | |
46 | + } | |
47 | + searchTextFieldView.snp.makeConstraints { make in | |
48 | + make.leading.equalTo(searchImageView).offset(32.sizeW) | |
49 | + make.trailing.equalToSuperview().offset(-16.sizeW) | |
50 | + make.top.bottom.equalToSuperview().inset(8.sizeH) | |
51 | + } | |
52 | + } | |
53 | +} | |
54 | + | ... | ... |
1 | +// | |
2 | +// ToolbarView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 29.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +enum historyToolbarElementType { | |
11 | + case clean | |
12 | +} | |
13 | + | |
14 | +final class HistoryToolbarView: UIView { | |
15 | + var action: ((historyToolbarElementType) -> Void)? | |
16 | + | |
17 | + let cleanHistoryButton: UIButton = { | |
18 | + let obj = UIButton() | |
19 | + obj.setTitle("Clean", for: .normal) | |
20 | + obj.setTitleColor(.systemBlue, for: .normal) | |
21 | + let menuItems: [UIMenuElement] = menuCases.allCases.map { $0.action } | |
22 | + obj.menu = UIMenu(title: "Clearing will remove history, cookies and other browsing data. History will be cleared from devices signed into your iCloud Account. Clear from:", children: menuItems) | |
23 | + obj.showsMenuAsPrimaryAction = true | |
24 | + return obj | |
25 | + }() | |
26 | + | |
27 | + override init(frame: CGRect) { | |
28 | + super.init(frame: frame) | |
29 | + setup() | |
30 | + setupConstraints() | |
31 | + } | |
32 | + | |
33 | + required init?(coder: NSCoder) { | |
34 | + fatalError("init(coder:) has not been implemented") | |
35 | + } | |
36 | + | |
37 | + private func setup() { | |
38 | + backgroundColor = .white | |
39 | + addSubview(cleanHistoryButton) | |
40 | + } | |
41 | + | |
42 | + private func setupConstraints() { | |
43 | + cleanHistoryButton.snp.makeConstraints { make in | |
44 | + make.trailing.equalToSuperview().inset(20.sizeW) | |
45 | + make.height.equalTo(20.sizeH) | |
46 | + make.top.bottom.equalToSuperview() | |
47 | + } | |
48 | + } | |
49 | +} | |
50 | + | ... | ... |
1 | +// | |
2 | +// HistoryView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 29.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class HistoryView: UIView { | |
11 | + let historySearchBar: HistorySearchBarView = { | |
12 | + let obj = HistorySearchBarView() | |
13 | + obj.layer.cornerRadius = 10 | |
14 | + obj.backgroundColor = UIColor(red: 0.913, green: 0.913, blue: 0.947, alpha: 1) | |
15 | + return obj | |
16 | + }() | |
17 | + | |
18 | + let historyTabsTableView: UITableView = { | |
19 | + let obj = UITableView() | |
20 | + obj.separatorStyle = .none | |
21 | + return obj | |
22 | + }() | |
23 | + | |
24 | + let historyToolbarView: HistoryToolbarView = { | |
25 | + let obj = HistoryToolbarView() | |
26 | + return obj | |
27 | + }() | |
28 | + | |
29 | + override init(frame: CGRect) { | |
30 | + super.init(frame: frame) | |
31 | + setup() | |
32 | + } | |
33 | + | |
34 | + required init?(coder: NSCoder) { | |
35 | + fatalError("init(coder:) has not been implemented") | |
36 | + } | |
37 | + | |
38 | + private func setup() { | |
39 | + backgroundColor = .gray.withAlphaComponent(0.1) | |
40 | + addSubview(historySearchBar) | |
41 | + addSubview(historyTabsTableView) | |
42 | + addSubview(historyToolbarView) | |
43 | + setupConstraints() | |
44 | + } | |
45 | + | |
46 | + private func setupConstraints() { | |
47 | + historySearchBar.snp.makeConstraints { make in | |
48 | + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH) | |
49 | + make.leading.trailing.equalToSuperview().inset(16.sizeW) | |
50 | + } | |
51 | + | |
52 | + historyTabsTableView.snp.makeConstraints { make in | |
53 | + make.top.equalTo(historySearchBar.snp.bottom).offset(32.sizeH) | |
54 | + make.bottom.equalTo(historyToolbarView.snp.top).inset(7.sizeH) | |
55 | + make.leading.trailing.equalToSuperview().inset(16.sizeW) | |
56 | + make.height.equalTo(600.sizeH) | |
57 | + } | |
58 | + historyToolbarView.snp.makeConstraints { make in | |
59 | + make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom) | |
60 | + make.leading.trailing.equalToSuperview() | |
61 | + } | |
62 | + } | |
63 | +} | |
64 | + | |
65 | +//MARK: - Helpers | |
66 | +extension HistoryView: UITextFieldDelegate { | |
67 | + func textFieldDidBeginEditing(_ textField: UITextField) { | |
68 | + historySearchBar.searchTextFieldView.text = "" | |
69 | + } | |
70 | +} | |
71 | + | |
72 | + | ... | ... |
1 | +// | |
2 | +// ViewController.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 25.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import SnapKit | |
10 | +import WebKit | |
11 | +import Combine | |
12 | +import Realm | |
13 | + | |
14 | +final class BrowserHomeViewController: UIViewController { | |
15 | + private let images = StringConstants.browserHomeVCImages | |
16 | + private let searchingViewController = SearchingViewController(dataForReq: []) | |
17 | + private let searchResultViewController = SearchResultViewController(searchLink: String()) | |
18 | + private var subscriptions: Set<AnyCancellable> = [] | |
19 | + private var finalSearchRequest = URLConstants.googleURL | |
20 | + private let tabsViewController = TabsViewController() | |
21 | + private var currentTabId: Int? | |
22 | + | |
23 | + let mainView = BrowserHomeView() | |
24 | + | |
25 | + private var url: String? { | |
26 | + didSet { | |
27 | + finalSearchRequest = url ?? String() | |
28 | + openSearchResult() | |
29 | + } | |
30 | + } | |
31 | + | |
32 | + override func viewDidLoad() { | |
33 | + super.viewDidLoad() | |
34 | + view.backgroundColor = ColorConstants.lightGray | |
35 | + initViewController() | |
36 | + } | |
37 | + | |
38 | + override func viewWillAppear(_ animated: Bool) { | |
39 | + keyboardObserver() | |
40 | + } | |
41 | + | |
42 | + private func initViewController() { | |
43 | + setupCollectionView() | |
44 | + addTargets() | |
45 | + setupSearchBarComponentsAction() | |
46 | + setupSearchingViewController() | |
47 | + progressObserver() | |
48 | + } | |
49 | + | |
50 | + override func viewIsAppearing(_ animated: Bool) { | |
51 | + navigationController?.isNavigationBarHidden = true | |
52 | + } | |
53 | + | |
54 | + override func loadView() { | |
55 | + view = mainView | |
56 | + } | |
57 | + | |
58 | + init(url: String?, currentTabId: Int?) { | |
59 | + super.init(nibName: nil, bundle: nil) | |
60 | + self.url = url | |
61 | + self.currentTabId = currentTabId | |
62 | + } | |
63 | + | |
64 | + required init?(coder: NSCoder) { | |
65 | + fatalError("init(coder:) has not been implemented") | |
66 | + } | |
67 | + | |
68 | + override func viewWillDisappear(_ animated: Bool) { | |
69 | + super.viewWillDisappear(animated) | |
70 | + NotificationCenter.default.removeObserver(self) | |
71 | + } | |
72 | +} | |
73 | + | |
74 | + | |
75 | +//MARK: CollectionView Setup | |
76 | +extension BrowserHomeViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { | |
77 | + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { | |
78 | + images.count | |
79 | + } | |
80 | + | |
81 | + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | |
82 | + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TabCollectionViewCell", for: indexPath) as? TabCollectionViewCell else { | |
83 | + return TabCollectionViewCell() | |
84 | + } | |
85 | + let finalCell = setupCellForCollectionView(cell, indexPath) | |
86 | + return finalCell | |
87 | + } | |
88 | + | |
89 | + private func setupCellForCollectionView(_ cell: TabCollectionViewCell, _ indexPath: IndexPath) -> TabCollectionViewCell { | |
90 | + let imageName = images[indexPath.item] | |
91 | + cell.tabCellImage.image = UIImage(named: imageName) | |
92 | + cell.tabCellLabel.text = imageName | |
93 | + cell.backgroundColor = .white | |
94 | + return cell | |
95 | + } | |
96 | + | |
97 | + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { | |
98 | + return CGSize(width: 72.sizeW, height: 94.sizeH) | |
99 | + } | |
100 | + | |
101 | + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { | |
102 | + finalSearchRequest = StringConstants.browserHomeVCurl[indexPath.row] | |
103 | + openSearchResult() | |
104 | + } | |
105 | + | |
106 | + private func setupCollectionView() { | |
107 | + mainView.frequentlyVisitedCollectionView.dataSource = self | |
108 | + mainView.frequentlyVisitedCollectionView.delegate = self | |
109 | + mainView.frequentlyVisitedCollectionView.register(TabCollectionViewCell.self, forCellWithReuseIdentifier: "TabCollectionViewCell") | |
110 | + } | |
111 | +} | |
112 | + | |
113 | + | |
114 | +//MARK: - Keyboard extention | |
115 | +extension BrowserHomeViewController { | |
116 | + func keyboardObserver() { | |
117 | + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear), name: UIResponder.keyboardWillHideNotification, object: nil) | |
118 | + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) | |
119 | + } | |
120 | +} | |
121 | + | |
122 | + | |
123 | +//MARK: - Action | |
124 | +extension BrowserHomeViewController { | |
125 | + @objc private func searchResultAction() { | |
126 | + removeChildViewController() | |
127 | + mainView.searchBarContainer.searchBarView.searchTextFieldView.text = nil | |
128 | + mainView.searchBarContainer.searchBarView.cleanTextFieldButton.isHidden = true | |
129 | + } | |
130 | + | |
131 | + func searchAndReloadTableView() async { | |
132 | + let sitesFromSearch: [String] = await BrowserSearchService().searchSuggest(finalSearchRequest) | |
133 | + if !sitesFromSearch.isEmpty { | |
134 | + searchingViewController.dataForReq = sitesFromSearch | |
135 | + } | |
136 | + addingSearchingViewController(searchingViewController) | |
137 | + } | |
138 | + | |
139 | + @objc | |
140 | + func keyboardWillShow(_ notification: Notification) { | |
141 | + guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } | |
142 | + let keyboardHeight = keyboardFrame.height | |
143 | + self.mainView.animateSearchBar(keyboardHeight) | |
144 | + } | |
145 | + | |
146 | + @objc | |
147 | + func keyboardWillDisappear() { | |
148 | + mainView.animateSearchBarDismiss() | |
149 | + } | |
150 | + | |
151 | + @objc | |
152 | + private func settingButtonTapped(_ sender: UIButton) { | |
153 | + let settingViewController = SettingViewController() | |
154 | + openAdditionViewController(settingViewController) | |
155 | + } | |
156 | + | |
157 | + @objc | |
158 | + private func removeAdButtonTapped(_ sender: UIButton) { | |
159 | + let removeAdViewController = RemoveAdvertViewController() | |
160 | + openAdditionViewController(removeAdViewController) | |
161 | + } | |
162 | + | |
163 | + @objc | |
164 | + private func removeSearchingViewController(_ sender: UIButton) { | |
165 | + searchResultAction() | |
166 | + } | |
167 | + | |
168 | + func didTabButtonTapped(type: ToolbarElementType) { | |
169 | + switch type { | |
170 | + case .history: | |
171 | + let historyViewController = HistoryViewController() | |
172 | + present(historyViewController, animated: true, completion: nil) | |
173 | + break | |
174 | + case .tabs: | |
175 | + tabsButtonHandler() | |
176 | + break | |
177 | + case .back: | |
178 | + searchResultViewController.mainView.searchResultView.goBack() | |
179 | + break | |
180 | + case .forward: | |
181 | + searchResultViewController.mainView.searchResultView.goForward() | |
182 | + break | |
183 | + case .share: | |
184 | + let items = [URL(string: finalSearchRequest)] | |
185 | + let shareView = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil) | |
186 | + present(shareView, animated: true) | |
187 | + break | |
188 | + } | |
189 | + } | |
190 | +} | |
191 | + | |
192 | + | |
193 | +//MARK: - Helpers | |
194 | +extension BrowserHomeViewController { | |
195 | + private func addTargets() { | |
196 | + mainView.settingButton.addTarget(self, action: #selector(settingButtonTapped(_ :)), for: .touchUpInside) | |
197 | + mainView.removeAddButton.addTarget(self, action: #selector(removeAdButtonTapped(_ :)), for: .touchUpInside) | |
198 | + mainView.searchBarContainer.searchBarView.searchTextFieldView.addTarget(self, action: #selector(searchBarTextChanged), for: .editingChanged) | |
199 | + searchingViewController.mainView.searchingButton.addTarget(self, action: #selector(removeSearchingViewController(_ :)), for: .touchUpInside) | |
200 | + addToolbarTargets() | |
201 | + } | |
202 | + | |
203 | + private func addToolbarTargets() { | |
204 | + mainView.toolbarView.action = didTabButtonTapped | |
205 | + } | |
206 | + | |
207 | + private func openAdditionViewController(_ viewController: UIViewController) { | |
208 | + viewController.modalPresentationStyle = .fullScreen | |
209 | + present(viewController, animated: true, completion: nil) | |
210 | + } | |
211 | + | |
212 | + private func setupSearchingViewController() { | |
213 | + searchingViewController.searchCell = { [self] cell in | |
214 | + guard let cell = cell as? SearchingTableViewCell else { | |
215 | + return | |
216 | + } | |
217 | + finalSearchRequest = "https://www.google.com/search?q=" + (cell.searchLabel.text ?? "") | |
218 | + openSearchResult() | |
219 | + mainView.searchBarContainer.searchBarView.searchTextFieldView.endEditing(true) | |
220 | + } | |
221 | + } | |
222 | + | |
223 | + private func openSearchResult() { | |
224 | + let finalSearchRequest = finalSearchRequest.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) | |
225 | + searchResultViewController.searchLink = finalSearchRequest ?? "" | |
226 | + if let localUrl = URL(string: finalSearchRequest ?? "") { | |
227 | + let request = URLRequest(url: localUrl) | |
228 | + print(request) | |
229 | + searchResultViewController.mainView.searchResultView.load(request) | |
230 | + } | |
231 | + addingSearchingViewController(searchResultViewController) | |
232 | + } | |
233 | + | |
234 | + private func tabsButtonHandler() { | |
235 | + if currentTabId == nil { | |
236 | + addNewTab() | |
237 | + navigationController?.popViewController(animated: true) | |
238 | + } else { | |
239 | + updateCurrentTab() | |
240 | + } | |
241 | + } | |
242 | + | |
243 | + private func addNewTab() { | |
244 | + if let childViewController = self.children.first as? SearchResultViewController { | |
245 | + guard let siteTitle = childViewController.mainView.searchResultView.title else { | |
246 | + return | |
247 | + } | |
248 | + guard let siteUrl = childViewController.mainView.searchResultView.url else { | |
249 | + return | |
250 | + } | |
251 | + let finalUrl = siteUrl.absoluteString | |
252 | + let lastVisit = DateManager.shared.currentDate | |
253 | + let wkWVForSnapshot = childViewController.mainView.searchResultView | |
254 | + | |
255 | + SnapshotService.shared.makeWKWebViewSnapshot(wkWVForSnapshot) { snapshotForDB in | |
256 | + TabManager.shared.saveTab(tabTitle: siteTitle, snapshotImage: snapshotForDB, tabUrl: finalUrl) | |
257 | + } | |
258 | + HistoryDBManager.shared.saveToHistory(siteTitle: siteTitle, siteUrl: finalUrl, lastVisit: lastVisit) | |
259 | + } else { | |
260 | + let homeViewSnapshot = SnapshotService.shared.makeSnapshot(mainView) | |
261 | + TabManager.shared.saveTab(tabTitle: "Start Page", snapshotImage: homeViewSnapshot, tabUrl: "homeUrl") | |
262 | + currentTabId = tabsViewController.getCellIndex().row | |
263 | + } | |
264 | + } | |
265 | + | |
266 | + private func updateCurrentTab() { | |
267 | + let allTabs = TabManager.shared.getAllTabs() | |
268 | + let chosenTab = allTabs[self.currentTabId ?? Int()] | |
269 | + let gottedCellId = chosenTab.tabId | |
270 | + let imageForUpdatedTab = SnapshotService.shared.makeSnapshot(self.mainView) | |
271 | + if let childViewController = self.children.first as? SearchResultViewController { | |
272 | + guard let siteTitle = childViewController.mainView.searchResultView.title else { | |
273 | + return | |
274 | + } | |
275 | + guard let siteUrl = childViewController.mainView.searchResultView.url?.absoluteString else { | |
276 | + return | |
277 | + } | |
278 | + let lastDate = DateManager.shared.currentDate | |
279 | + | |
280 | + TabManager.shared.updateTab(tabId: gottedCellId, newTabTitle: siteTitle, newSnapshotImage: imageForUpdatedTab, newTabUrl: siteUrl) { result in | |
281 | + self.navigationController?.popViewController(animated: true) | |
282 | + } | |
283 | + HistoryDBManager.shared.saveToHistory(siteTitle: siteTitle, siteUrl: siteUrl, lastVisit: lastDate) | |
284 | + } else { | |
285 | + TabManager.shared.updateTab(tabId: gottedCellId, newTabTitle: "Start Page", newSnapshotImage: imageForUpdatedTab, newTabUrl: "homeUrl") { result in | |
286 | + self.navigationController?.popViewController(animated: true) | |
287 | + } | |
288 | + } | |
289 | + } | |
290 | +} | |
291 | + | |
292 | + | |
293 | +//MARK: - ChildVC actions | |
294 | +extension BrowserHomeViewController { | |
295 | + func addingSearchingViewController(_ childViewController: UIViewController) { | |
296 | + if self.children.isEmpty { | |
297 | + addNewChildViewController(childViewController) | |
298 | + } else { | |
299 | + removeChildViewController() | |
300 | + addNewChildViewController(childViewController) | |
301 | + } | |
302 | + } | |
303 | + | |
304 | + func addNewChildViewController(_ child: UIViewController) { | |
305 | + addChild(child) | |
306 | + mainView.addSearchView(child.view) | |
307 | + child.didMove(toParent: self) | |
308 | + } | |
309 | + | |
310 | + func removeChildViewController() { | |
311 | + if let childViewController = self.children.first as? SearchingViewController { | |
312 | + childViewController.view.removeFromSuperview() | |
313 | + childViewController.willMove(toParent: nil) | |
314 | + childViewController.removeFromParent() | |
315 | + } | |
316 | + if let childViewController = self.children.first as? SearchResultViewController { | |
317 | + childViewController.view.removeFromSuperview() | |
318 | + childViewController.willMove(toParent: nil) | |
319 | + childViewController.removeFromParent() | |
320 | + } | |
321 | + } | |
322 | +} | |
323 | + | |
324 | + | |
325 | +//MARK: - SearchBar extention | |
326 | +extension BrowserHomeViewController: UITextFieldDelegate { | |
327 | + @objc | |
328 | + func searchBarTextChanged() { | |
329 | + if let text = mainView.searchBarContainer.searchBarView.searchTextFieldView.text { | |
330 | + finalSearchRequest = text | |
331 | + mainView.searchBarContainer.searchBarView.cleanTextFieldButton.isHidden = false | |
332 | + if finalSearchRequest.isEmpty { | |
333 | + searchResultAction() | |
334 | + } else { | |
335 | + Task { | |
336 | + await searchAndReloadTableView() | |
337 | + } | |
338 | + } | |
339 | + } | |
340 | + } | |
341 | + | |
342 | + func textFieldDidBeginEditing(_ textField: UITextField) { | |
343 | + mainView.searchBarContainer.searchBarView.searchTextFieldView.text = nil | |
344 | + mainView.searchBarContainer.searchBarView.searchTextFieldView.textColor = .black | |
345 | + } | |
346 | + | |
347 | + func textFieldShouldReturn(_ textField: UITextField) -> Bool { | |
348 | + finalSearchRequest = "https://www.google.com/search?q=" + (textField.text ?? "") | |
349 | + openSearchResult() | |
350 | + textField.resignFirstResponder() | |
351 | + return true | |
352 | + } | |
353 | + | |
354 | + func setupSearchBarComponentsAction() { | |
355 | + mainView.searchBarContainer.searchBarView.searchTextFieldView.autocorrectionType = .no | |
356 | + isButtonClickable() | |
357 | + mainView.searchBarContainer.searchBarView.searchTextFieldView.delegate = self | |
358 | + mainView.searchBarContainer.searchBarView.cleanTextFieldButton.addTarget(self, action: #selector(searchResultAction), for: .touchUpInside) | |
359 | + } | |
360 | +} | |
361 | + | |
362 | + | |
363 | +//MARK: - WebView extention | |
364 | +extension BrowserHomeViewController { | |
365 | + func isButtonClickable() { | |
366 | + searchResultViewController.mainView.searchResultView | |
367 | + .publisher(for: \.canGoBack) | |
368 | + .sink { [weak self] canGoBack in | |
369 | + self?.mainView.toolbarView.backBarButtonItem.isEnabled = canGoBack | |
370 | + } | |
371 | + .store(in: &subscriptions) | |
372 | + | |
373 | + searchResultViewController.mainView.searchResultView | |
374 | + .publisher(for: \.canGoForward) | |
375 | + .sink { [weak self] canGoForward in | |
376 | + self?.mainView.toolbarView.forwardBarButtonItem.isEnabled = canGoForward | |
377 | + } | |
378 | + .store(in: &subscriptions) | |
379 | + | |
380 | + searchResultViewController.mainView.searchResultView | |
381 | + .publisher(for: \.isLoading) | |
382 | + .sink { [weak self] isLoading in | |
383 | + guard let self = self else { return } | |
384 | + if let url = self.searchResultViewController.mainView.searchResultView.url { | |
385 | + self.finalSearchRequest = url.absoluteString | |
386 | + } | |
387 | + } | |
388 | + .store(in: &subscriptions) | |
389 | + } | |
390 | + | |
391 | + private func progressObserver() { | |
392 | + searchResultViewController.mainView.searchResultView | |
393 | + .publisher(for: \.estimatedProgress) | |
394 | + .sink { [weak self] progress in | |
395 | + guard let self = self else { return } | |
396 | + self.mainView.searchBarContainer.searchBarView.progressBar.progress = Float(progress) | |
397 | + if progress == 1 { | |
398 | + self.mainView.searchBarContainer.searchBarView.progressBar.isHidden = true | |
399 | + self.mainView.toolbarView.shareBarButtonItem.isEnabled = true | |
400 | + } else if progress == 0 { | |
401 | + self.mainView.searchBarContainer.searchBarView.progressBar.isHidden = true | |
402 | + } else { | |
403 | + self.mainView.searchBarContainer.searchBarView.progressBar.isHidden = false | |
404 | + self.mainView.toolbarView.shareBarButtonItem.isEnabled = false | |
405 | + } | |
406 | + } | |
407 | + .store(in: &subscriptions) | |
408 | + } | |
409 | + } | |
410 | + | |
411 | +extension BrowserHomeViewController { | |
412 | + func urlManagment(_ url: String) { | |
413 | + finalSearchRequest = url | |
414 | + openSearchResult() | |
415 | + } | |
416 | +} | ... | ... |
1 | +// | |
2 | +// MainView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 25.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import SnapKit | |
10 | + | |
11 | +final class BrowserHomeView: UIView { | |
12 | + let removeAddButton: UIButton = { | |
13 | + let obj = UIButton() | |
14 | + obj.backgroundColor = ColorConstants.buttonsBackgroundColor | |
15 | + obj.setTitle("Remove advert", for: .normal) | |
16 | + obj.titleLabel?.font = FontConstants.semiboldFont_15 | |
17 | + obj.translatesAutoresizingMaskIntoConstraints = false | |
18 | + obj.setTitleColor(.white, for: .normal) | |
19 | + obj.setImage(UIImage(systemName: "shield.lefthalf.filled")?.withTintColor(.white, renderingMode: .alwaysOriginal), for: .normal) | |
20 | + obj.layer.cornerRadius = 10 | |
21 | + obj.contentEdgeInsets = UIEdgeInsets(top: 10.sizeW, left: 10.sizeW, bottom: 10.sizeW, right: 10.sizeW) | |
22 | + obj.clipsToBounds = true | |
23 | + obj.layer.masksToBounds = false | |
24 | + return obj | |
25 | + }() | |
26 | + | |
27 | + let settingButton: UIButton = { | |
28 | + let obj = UIButton() | |
29 | + obj.setImage(UIImage(named: "Settings")?.withTintColor(.systemBlue), for: .normal) | |
30 | + return obj | |
31 | + }() | |
32 | + | |
33 | + let titleLabel: UILabel = { | |
34 | + let obj = UILabel() | |
35 | + obj.text = StringConstants.frequentlyVisited | |
36 | + obj.font = FontConstants.semiboldFont_18 | |
37 | + return obj | |
38 | + }() | |
39 | + | |
40 | + let frequentlyVisitedCollectionView: UICollectionView = { | |
41 | + let obj = UICollectionViewFlowLayout() | |
42 | + obj.minimumInteritemSpacing = 12.sizeW | |
43 | + obj.scrollDirection = .horizontal | |
44 | + obj.sectionInset = UIEdgeInsets(top: 4.sizeH, left: 4.sizeW, bottom: 4.sizeH, right: 4.sizeW) | |
45 | + | |
46 | + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: obj) | |
47 | + collectionView.backgroundColor = .clear | |
48 | + collectionView.showsHorizontalScrollIndicator = false | |
49 | + return collectionView | |
50 | + }() | |
51 | + | |
52 | + let toolbarView: ToolbarView = { | |
53 | + let obj = ToolbarView() | |
54 | + return obj | |
55 | + }() | |
56 | + | |
57 | + let searchBarContainer: SearchBarContainer = { | |
58 | + let obj = SearchBarContainer() | |
59 | + obj.backgroundColor = .clear | |
60 | + return obj | |
61 | + }() | |
62 | + | |
63 | + override init(frame: CGRect) { | |
64 | + super.init(frame: frame) | |
65 | + setup() | |
66 | + setupConstraints() | |
67 | + } | |
68 | + | |
69 | + required init?(coder: NSCoder) { | |
70 | + fatalError("init(coder:) has not been implemented") | |
71 | + } | |
72 | + | |
73 | + private func setup() { | |
74 | + addSubview(titleLabel) | |
75 | + addSubview(frequentlyVisitedCollectionView) | |
76 | + addSubview(removeAddButton) | |
77 | + addSubview(settingButton) | |
78 | + addSubview(searchBarContainer) | |
79 | + addSubview(toolbarView) | |
80 | + } | |
81 | + | |
82 | + private func setupConstraints() { | |
83 | + removeAddButton.snp.makeConstraints { make in | |
84 | + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH) | |
85 | + make.leading.equalTo(safeAreaLayoutGuide.snp.leading).offset(20.sizeW) | |
86 | + make.trailing.equalToSuperview().offset(-158.sizeW) | |
87 | + } | |
88 | + settingButton.snp.makeConstraints { make in | |
89 | + make.centerY.equalTo(removeAddButton) | |
90 | + make.height.equalTo(24.sizeH) | |
91 | + make.width.equalTo(24.sizeH) | |
92 | + make.trailing.equalToSuperview().offset(-16.sizeW) | |
93 | + } | |
94 | + titleLabel.snp.makeConstraints { make in | |
95 | + make.top.equalTo(removeAddButton.snp.bottom).offset(64.sizeH) | |
96 | + make.leading.equalTo(safeAreaLayoutGuide.snp.leading).offset(16.sizeW) | |
97 | + } | |
98 | + frequentlyVisitedCollectionView.snp.makeConstraints { make in | |
99 | + make.leading.trailing.equalToSuperview().inset(24.sizeW) | |
100 | + make.height.equalTo(120.sizeH) | |
101 | + make.top.equalTo(titleLabel.snp.bottom).offset(8.sizeH) | |
102 | + } | |
103 | + toolbarView.snp.makeConstraints { make in | |
104 | + make.leading.equalToSuperview() | |
105 | + make.trailing.equalToSuperview() | |
106 | + make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom) | |
107 | + } | |
108 | + searchBarContainer.snp.makeConstraints { make in | |
109 | + make.leading.equalToSuperview() | |
110 | + make.trailing.equalToSuperview() | |
111 | + make.bottom.equalToSuperview().offset(-90.sizeH) | |
112 | + } | |
113 | + } | |
114 | +} | |
115 | + | |
116 | +//MARK: - childView extension | |
117 | +extension BrowserHomeView { | |
118 | + func addSearchView(_ childView: UIView){ | |
119 | + addSubview(childView) | |
120 | + childView.snp.makeConstraints { make in | |
121 | + make.top.equalToSuperview() | |
122 | + make.leading.trailing.equalToSuperview() | |
123 | + make.bottom.equalTo(searchBarContainer.snp.top).offset(-2.sizeH) | |
124 | + } | |
125 | + } | |
126 | +} | |
127 | + | |
128 | +//MARK: - Search bar extention | |
129 | +extension BrowserHomeView { | |
130 | + func animateSearchBar(_ keyboardHeight: CGFloat) { | |
131 | + UIView.animate(withDuration: 0.3) { | |
132 | + self.searchBarContainer.backgroundColor = UIColor(red: 0.808, green: 0.823, blue: 0.85, alpha: 0.9) | |
133 | + self.searchBarContainer.snp.updateConstraints { make in | |
134 | + make.leading.equalToSuperview() | |
135 | + make.trailing.equalToSuperview() | |
136 | + make.bottom.equalToSuperview().offset(-keyboardHeight) | |
137 | + } | |
138 | + self.layoutIfNeeded() | |
139 | + } | |
140 | + } | |
141 | + | |
142 | + func animateSearchBarDismiss() { | |
143 | + BrowserHomeView.animate(withDuration: 0.3) { | |
144 | + self.searchBarContainer.backgroundColor = .clear | |
145 | + self.searchBarContainer.snp.updateConstraints { make in | |
146 | + make.leading.equalToSuperview() | |
147 | + make.trailing.equalToSuperview() | |
148 | + make.bottom.equalToSuperview().offset(-90.sizeH) | |
149 | + } | |
150 | + } | |
151 | + self.layoutIfNeeded() | |
152 | + } | |
153 | +} | ... | ... |
1 | +// | |
2 | +// tabCell.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 25.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class TabCollectionViewCell: UICollectionViewCell { | |
11 | + let tabCellImage: UIImageView = { | |
12 | + let obj = UIImageView() | |
13 | + obj.contentMode = .scaleToFill | |
14 | + return obj | |
15 | + }() | |
16 | + | |
17 | + let tabCellLabel: UILabel = { | |
18 | + let obj = UILabel() | |
19 | + obj.textColor = .black | |
20 | + obj.font = FontConstants.regularFont_14 | |
21 | + return obj | |
22 | + }() | |
23 | + | |
24 | + override init(frame: CGRect) { | |
25 | + super.init(frame: frame) | |
26 | + setup() | |
27 | + } | |
28 | + | |
29 | + required init?(coder: NSCoder) { | |
30 | + fatalError("init(coder:) has not been implemented") | |
31 | + } | |
32 | + | |
33 | + func setup() { | |
34 | + | |
35 | + layer.cornerRadius = 10 | |
36 | + contentView.backgroundColor = UIColor(red: 0.867, green: 0.867, blue: 0.863, alpha: 0.4) | |
37 | + contentView.layer.cornerRadius = 10 | |
38 | + contentView.addSubview(tabCellImage) | |
39 | + contentView.addSubview(tabCellLabel) | |
40 | + setupConstraints() | |
41 | + } | |
42 | + | |
43 | + private func setupConstraints() { | |
44 | + tabCellImage.snp.makeConstraints { make in | |
45 | + make.top.equalToSuperview().offset(14.sizeH) | |
46 | + make.leading.trailing.equalToSuperview().inset(9.sizeW) | |
47 | + make.height.equalTo(50.sizeW) | |
48 | + } | |
49 | + | |
50 | + tabCellLabel.snp.makeConstraints { make in | |
51 | + make.centerX.equalToSuperview() | |
52 | + make.top.equalTo(tabCellImage.snp.bottom).offset(8.sizeH) | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + override func layoutSubviews() { | |
57 | + super.layoutSubviews() | |
58 | + shadowSetup() | |
59 | + } | |
60 | +} | |
61 | + | |
62 | +//MARK: - Shadows | |
63 | +extension TabCollectionViewCell { | |
64 | + private func shadowSetup() { | |
65 | + layer.shadowColor = UIColor.gray.cgColor | |
66 | + layer.shadowOpacity = 0.2 | |
67 | + layer.shadowRadius = 3 | |
68 | + layer.shadowOffset = CGSize(width: 2, height: 2) | |
69 | + } | |
70 | +} | ... | ... |
1 | +// | |
2 | +// SearchBarSpace.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 12.10.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class SearchBarContainer: UIView { | |
11 | + let searchBarView: SearchBarView = { | |
12 | + let obj = SearchBarView() | |
13 | + obj.backgroundColor = .white | |
14 | + obj.layer.cornerRadius = 10 | |
15 | + obj.layer.shadowColor = UIColor.black.withAlphaComponent(0.1).cgColor | |
16 | + obj.layer.shadowOpacity = 1 | |
17 | + obj.layer.shadowRadius = 10 | |
18 | + obj.layer.shadowOffset = CGSize(width: 0, height: 4.sizeW) | |
19 | + return obj | |
20 | + }() | |
21 | + | |
22 | + override init(frame: CGRect) { | |
23 | + super.init(frame: frame) | |
24 | + setup() | |
25 | + setupConstraints() | |
26 | + } | |
27 | + | |
28 | + required init?(coder: NSCoder) { | |
29 | + fatalError("init(coder:) has not been implemented") | |
30 | + } | |
31 | + | |
32 | + private func setup() { | |
33 | + addSubview(searchBarView) | |
34 | + } | |
35 | + | |
36 | + private func setupConstraints() { | |
37 | + searchBarView.snp.makeConstraints { make in | |
38 | + make.top.equalToSuperview().offset(4.sizeH) | |
39 | + make.leading.equalToSuperview().offset(16.sizeW) | |
40 | + make.trailing.equalToSuperview().offset(-16.sizeW) | |
41 | + make.bottom.equalToSuperview().offset(-6.sizeH) | |
42 | + } | |
43 | + } | |
44 | +} | ... | ... |
1 | +// | |
2 | +// SearchBarView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 26.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class SearchBarView: UIView { | |
11 | + let searchImageView: UIImageView = { | |
12 | + let obj = UIImageView() | |
13 | + let magnifyImage = UIImage(systemName: "magnifyingglass")?.withTintColor(.gray, renderingMode: .alwaysOriginal) | |
14 | + obj.image = magnifyImage | |
15 | + return obj | |
16 | + }() | |
17 | + | |
18 | + let searchTextFieldView: UITextField = { | |
19 | + let obj = UITextField() | |
20 | + obj.text = "Search" | |
21 | + obj.textColor = ColorConstants.gray | |
22 | + return obj | |
23 | + }() | |
24 | + | |
25 | + let cleanTextFieldButton: UIButton = { | |
26 | + let obj = UIButton() | |
27 | + obj.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal) | |
28 | + obj.tintColor = .black | |
29 | + obj.isHidden = true | |
30 | + return obj | |
31 | + }() | |
32 | + | |
33 | + let progressBar: UIProgressView = { | |
34 | + let obj = UIProgressView(progressViewStyle: .default) | |
35 | + obj.progressTintColor = .systemIndigo | |
36 | + obj.progress = 0 | |
37 | + obj.translatesAutoresizingMaskIntoConstraints = false | |
38 | + return obj | |
39 | + }() | |
40 | + | |
41 | + override init(frame: CGRect) { | |
42 | + super.init(frame: frame) | |
43 | + setup() | |
44 | + setupConstraints() | |
45 | + } | |
46 | + | |
47 | + required init?(coder: NSCoder) { | |
48 | + fatalError("init(coder:) has not been implemented") | |
49 | + } | |
50 | + | |
51 | + private func setup() { | |
52 | + addSubview(progressBar) | |
53 | + addSubview(searchImageView) | |
54 | + addSubview(searchTextFieldView) | |
55 | + addSubview(cleanTextFieldButton) | |
56 | + } | |
57 | + | |
58 | + private func setupConstraints() { | |
59 | + searchImageView.snp.makeConstraints { make in | |
60 | + make.leading.equalToSuperview().offset(16.sizeW) | |
61 | + make.top.bottom.equalToSuperview().inset(8.sizeH) | |
62 | + } | |
63 | + searchTextFieldView.snp.makeConstraints { make in | |
64 | + make.leading.equalTo(searchImageView).offset(32.sizeW) | |
65 | + make.trailing.equalToSuperview().offset(-16.sizeW) | |
66 | + make.top.bottom.equalToSuperview().inset(8.sizeH) | |
67 | + } | |
68 | + cleanTextFieldButton.snp.makeConstraints { make in | |
69 | + make.trailing.equalToSuperview().offset(-16.sizeW) | |
70 | + make.top.bottom.equalToSuperview().inset(8.sizeH) | |
71 | + } | |
72 | + progressBar.snp.makeConstraints { make in | |
73 | + make.bottom.equalToSuperview().inset(2.sizeH) | |
74 | + make.leading.trailing.equalToSuperview() | |
75 | + make.height.equalTo(2) | |
76 | + } | |
77 | + } | |
78 | +} | ... | ... |
1 | +// | |
2 | +// UINavigationToolbar.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 27.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +enum ToolbarElementType { | |
11 | + case back | |
12 | + case forward | |
13 | + case share | |
14 | + case history | |
15 | + case tabs | |
16 | +} | |
17 | + | |
18 | +final class ToolbarView: UIView { | |
19 | + var action: ((ToolbarElementType) -> Void)? | |
20 | + | |
21 | + let toolbar: UIToolbar = { | |
22 | + let obj = UIToolbar() | |
23 | + obj.sizeToFit() | |
24 | + obj.barTintColor = ColorConstants.lightGray | |
25 | + obj.clipsToBounds = true | |
26 | + return obj | |
27 | + }() | |
28 | + | |
29 | + let backBarButtonItem: UIBarButtonItem = { | |
30 | + let obj = UIBarButtonItem() | |
31 | + obj.isEnabled = false | |
32 | + obj.image = UIImage(systemName: "chevron.backward") | |
33 | + return obj | |
34 | + }() | |
35 | + | |
36 | + let forwardBarButtonItem: UIBarButtonItem = { | |
37 | + let obj = UIBarButtonItem() | |
38 | + obj.isEnabled = false | |
39 | + obj.image = UIImage(systemName: "chevron.forward") | |
40 | + return obj | |
41 | + }() | |
42 | + | |
43 | + let shareBarButtonItem: UIBarButtonItem = { | |
44 | + let obj = UIBarButtonItem() | |
45 | + obj.isEnabled = false | |
46 | + obj.image = UIImage(systemName: "square.and.arrow.up") | |
47 | + return obj | |
48 | + }() | |
49 | + | |
50 | + let historyBarButtonItem: UIBarButtonItem = { | |
51 | + let obj = UIBarButtonItem() | |
52 | + obj.image = UIImage(systemName: "book") | |
53 | + return obj | |
54 | + }() | |
55 | + | |
56 | + let tabsBarButtonItem: UIBarButtonItem = { | |
57 | + let obj = UIBarButtonItem() | |
58 | + obj.image = UIImage(systemName: "square.on.square") | |
59 | + return obj | |
60 | + }() | |
61 | + | |
62 | + override init(frame: CGRect) { | |
63 | + super.init(frame: frame) | |
64 | + setup() | |
65 | + } | |
66 | + | |
67 | + required init?(coder: NSCoder) { | |
68 | + fatalError("init(coder:) has not been implemented") | |
69 | + } | |
70 | + | |
71 | + private func setup() { | |
72 | + addSubview(toolbar) | |
73 | + let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) | |
74 | + toolbar.items = [ | |
75 | + backBarButtonItem, | |
76 | + flexibleSpace, | |
77 | + forwardBarButtonItem, | |
78 | + flexibleSpace, | |
79 | + shareBarButtonItem, | |
80 | + flexibleSpace, | |
81 | + historyBarButtonItem, | |
82 | + flexibleSpace, | |
83 | + tabsBarButtonItem, | |
84 | + ] | |
85 | + initActions() | |
86 | + setupConstraints() | |
87 | + } | |
88 | + | |
89 | + private func setupConstraints() { | |
90 | + toolbar.snp.makeConstraints { make in | |
91 | + make.top.equalToSuperview() | |
92 | + make.leading.trailing.equalToSuperview() | |
93 | + make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom) | |
94 | + } | |
95 | + } | |
96 | +} | |
97 | + | |
98 | +// MARK: - Helpers | |
99 | +extension ToolbarView { | |
100 | + private func initActions() { | |
101 | + backBarButtonItem.action = #selector(didItemTapped(_:)) | |
102 | + backBarButtonItem.target = self | |
103 | + forwardBarButtonItem.action = #selector(didItemTapped(_:)) | |
104 | + forwardBarButtonItem.target = self | |
105 | + shareBarButtonItem.action = #selector(didItemTapped(_:)) | |
106 | + shareBarButtonItem.target = self | |
107 | + historyBarButtonItem.action = #selector(didItemTapped(_:)) | |
108 | + historyBarButtonItem.target = self | |
109 | + tabsBarButtonItem.action = #selector(didItemTapped(_:)) | |
110 | + tabsBarButtonItem.target = self | |
111 | + } | |
112 | +} | |
113 | + | |
114 | +// MARK: - Actions | |
115 | +extension ToolbarView { | |
116 | + @objc | |
117 | + private func didItemTapped(_ sender: UIBarButtonItem) { | |
118 | + guard let action else { | |
119 | + return | |
120 | + } | |
121 | + switch sender { | |
122 | + case backBarButtonItem: | |
123 | + action(.back) | |
124 | + case forwardBarButtonItem: | |
125 | + action(.forward) | |
126 | + case shareBarButtonItem: | |
127 | + action(.share) | |
128 | + case historyBarButtonItem: | |
129 | + action(.history) | |
130 | + case tabsBarButtonItem: | |
131 | + action(.tabs) | |
132 | + default: | |
133 | + break | |
134 | + } | |
135 | + } | |
136 | +} | ... | ... |
1 | +// | |
2 | +// PayloadViewController.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 25.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class PayloadViewController: UIViewController { | |
11 | + private let mainView = PayloadView() | |
12 | + private let data = StringConstants.payloadViewControllerData | |
13 | + | |
14 | + override func viewDidLoad() { | |
15 | + super.viewDidLoad() | |
16 | + view.backgroundColor = ColorConstants.lightGray | |
17 | + initViewController() | |
18 | + } | |
19 | + | |
20 | + private func initViewController() { | |
21 | + setupTableView() | |
22 | + addTargets() | |
23 | + navigationController?.isNavigationBarHidden = true | |
24 | + } | |
25 | + | |
26 | + override func loadView() { | |
27 | + view = mainView | |
28 | + } | |
29 | + | |
30 | + init(){ | |
31 | + super.init(nibName: nil, bundle: nil) | |
32 | + } | |
33 | + required init?(coder: NSCoder) { | |
34 | + fatalError("init(coder:) has not been implemented") | |
35 | + } | |
36 | + | |
37 | + override func viewWillDisappear(_ animated: Bool) { | |
38 | + super.viewWillDisappear(animated) | |
39 | + NotificationCenter.default.removeObserver(self) | |
40 | + } | |
41 | +} | |
42 | + | |
43 | +extension PayloadViewController: UITableViewDelegate, UITableViewDataSource { | |
44 | + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
45 | + return data.count | |
46 | + } | |
47 | + | |
48 | + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
49 | + guard let cell = tableView.dequeueReusableCell(withIdentifier: "AdvantagesTableViewCell") as? | |
50 | + AdvantagesTableViewCell else { | |
51 | + return UITableViewCell() } | |
52 | + cell.advantagesCellLabel.text = data[indexPath.row] | |
53 | + cell.selectionStyle = .none | |
54 | + return cell | |
55 | + } | |
56 | + | |
57 | + private func setupTableView() { | |
58 | + mainView.advantagesTableView.dataSource = self | |
59 | + mainView.advantagesTableView.delegate = self | |
60 | + mainView.advantagesTableView.register(AdvantagesTableViewCell.self, forCellReuseIdentifier: StringConstants.advantagesTableViewCell) | |
61 | + } | |
62 | +} | |
63 | + | |
64 | + | |
65 | +//MARK: - Action | |
66 | +extension PayloadViewController { | |
67 | + @objc | |
68 | + private func getStartedButtonTapped(_ sender: UIButton) { | |
69 | + navigationController?.popViewController(animated: false) | |
70 | + } | |
71 | + | |
72 | + @objc | |
73 | + private func textPressed(_ sender: UITapGestureRecognizer) { | |
74 | + // navigationController?.popViewController(animated: false) | |
75 | + let termsViewController = TermsViewController() | |
76 | + termsViewController.modalPresentationStyle = .fullScreen | |
77 | + present(termsViewController, animated: true) | |
78 | + } | |
79 | + | |
80 | + private func addTargets() { | |
81 | + mainView.getStartedButton.addTarget(self, action: #selector(getStartedButtonTapped(_ :)), for: .touchUpInside) | |
82 | + mainView.privacyLabelView.isUserInteractionEnabled = true | |
83 | + mainView.privacyLabelView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(textPressed(_:)))) | |
84 | + | |
85 | + GestureSetup() | |
86 | + } | |
87 | + | |
88 | + private func GestureSetup() { | |
89 | + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(textPressed(_ :))) | |
90 | + mainView.infoLabel.addGestureRecognizer(tapGesture) | |
91 | + } | |
92 | +} | |
93 | + | |
94 | + | ... | ... |
1 | +// | |
2 | +// AdvantagesTableViewCell.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 26.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class AdvantagesTableViewCell: UITableViewCell { | |
11 | + let advantagesCellLabel: UILabel = { | |
12 | + let obj = UILabel() | |
13 | + obj.font = FontConstants.semiboldFont_14 | |
14 | + return obj | |
15 | + }() | |
16 | + | |
17 | + let advantagesCellImage: UIImageView = { | |
18 | + let obj = UIImageView() | |
19 | + let checkmarkImg = UIImage(systemName: "checkmark")?.withTintColor(.blue, renderingMode: .alwaysOriginal) | |
20 | + obj.image = checkmarkImg | |
21 | + obj.contentMode = .scaleToFill | |
22 | + return obj | |
23 | + }() | |
24 | + | |
25 | + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { | |
26 | + super.init(style: style, reuseIdentifier: reuseIdentifier) | |
27 | + setup() | |
28 | + | |
29 | + } | |
30 | + | |
31 | + required init?(coder: NSCoder) { | |
32 | + fatalError("init(coder:) has not been implemented") | |
33 | + } | |
34 | + | |
35 | + | |
36 | + | |
37 | + func setup() { | |
38 | + contentView.addSubview(advantagesCellLabel) | |
39 | + contentView.addSubview(advantagesCellImage) | |
40 | + setupConstraints() | |
41 | + backgroundColor = .clear | |
42 | + } | |
43 | + | |
44 | + private func setupConstraints() { | |
45 | + advantagesCellImage.snp.makeConstraints { make in | |
46 | + make.top.equalToSuperview().inset(5.sizeH) | |
47 | + make.bottom.equalToSuperview().inset(5.sizeH) | |
48 | + make.leading.equalToSuperview() | |
49 | + make.trailing.equalTo(advantagesCellLabel.snp.leading).offset(-8.sizeW) | |
50 | + } | |
51 | + advantagesCellLabel.snp.makeConstraints { make in | |
52 | + make.top.equalToSuperview().inset(5.sizeH) | |
53 | + make.bottom.equalToSuperview().inset(5.sizeH) | |
54 | + make.leading.equalTo(advantagesCellImage.snp.trailing) | |
55 | + make.trailing.equalToSuperview() | |
56 | + } | |
57 | + } | |
58 | +} | ... | ... |
1 | +// | |
2 | +// PayloadView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 25.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class PayloadView: UIView { | |
11 | + | |
12 | + let logoImageView: UIImageView = { | |
13 | + let obj = UIImageView() | |
14 | + obj.image = UIImage(named: "Gotoweb") | |
15 | + obj.contentMode = .scaleAspectFit | |
16 | + return obj | |
17 | + }() | |
18 | + | |
19 | + let phoneImageView: UIImageView = { | |
20 | + let obj = UIImageView() | |
21 | + obj.image = UIImage(named: "Phone") | |
22 | + obj.contentMode = .scaleAspectFit | |
23 | + return obj | |
24 | + }() | |
25 | + | |
26 | + let zoomedTabImageView: UIImageView = { | |
27 | + let obj = UIImageView() | |
28 | + obj.image = UIImage(named: "ZoomedTab") | |
29 | + obj.contentMode = .scaleAspectFit | |
30 | + return obj | |
31 | + }() | |
32 | + | |
33 | + let infoLabel: UILabel = { | |
34 | + let obj = UILabel() | |
35 | + obj.text = StringConstants.ourBrowser | |
36 | + obj.font = FontConstants.regularFont_12 | |
37 | + obj.numberOfLines = 0 | |
38 | + return obj | |
39 | + }() | |
40 | + | |
41 | + let advantagesTableView: UITableView = { | |
42 | + let obj = UITableView() | |
43 | + obj.backgroundColor = .clear | |
44 | + obj.isScrollEnabled = false | |
45 | + obj.separatorStyle = .none | |
46 | + return obj | |
47 | + }() | |
48 | + | |
49 | + let gradientLayer = CAGradientLayer() | |
50 | + | |
51 | + let getStartedButton: UIButton = { | |
52 | + let obj = UIButton() | |
53 | + obj.setTitle("Get started", for: .normal) | |
54 | + obj.titleLabel?.font = FontConstants.semiboldFont_17 | |
55 | + obj.setTitleColor(.white, for: .normal) | |
56 | + obj.layer.cornerRadius = 10 | |
57 | + obj.layer.masksToBounds = true | |
58 | + return obj | |
59 | + }() | |
60 | + | |
61 | + let privacyLabelView: UILabel = { | |
62 | + let obj = UILabel() | |
63 | + obj.textAlignment = .center | |
64 | + | |
65 | + let fullText = "By starting, you agree to our Terms and Condition and Privacy Policy." | |
66 | + let attributedText = NSMutableAttributedString(string: fullText) | |
67 | + attributedText.addAttribute(.foregroundColor, value: UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, range: NSRange(location: fullText.range(of: "Terms and Condition")?.lowerBound.utf16Offset(in: fullText) ?? 0, length: "Terms and Condition".count)) | |
68 | + attributedText.addAttribute(.foregroundColor, value: UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, range: NSRange(location: fullText.range(of: "Privacy Policy")?.lowerBound.utf16Offset(in: fullText) ?? 0, length: "Privacy Policy".count)) | |
69 | + obj.attributedText = attributedText | |
70 | + obj.font = FontConstants.regularFont_12 | |
71 | + obj.numberOfLines = 0 | |
72 | + obj.isUserInteractionEnabled = true | |
73 | + return obj | |
74 | + }() | |
75 | + | |
76 | + override init (frame: CGRect) { | |
77 | + super.init(frame: frame) | |
78 | + setup() | |
79 | + } | |
80 | + | |
81 | + required init?(coder: NSCoder) { | |
82 | + fatalError("init(coder:) has not been implemented") | |
83 | + } | |
84 | + | |
85 | + override func layoutSubviews() { | |
86 | + super.layoutSubviews() | |
87 | + gradientLayer.frame = getStartedButton.bounds | |
88 | + } | |
89 | + | |
90 | + private func setup() { | |
91 | + addSubview(logoImageView) | |
92 | + addSubview(phoneImageView) | |
93 | + addSubview(zoomedTabImageView) | |
94 | + addSubview(infoLabel) | |
95 | + addSubview(advantagesTableView) | |
96 | + addSubview(getStartedButton) | |
97 | + addSubview(privacyLabelView) | |
98 | + setupConstraints() | |
99 | + gradientSetup() | |
100 | + } | |
101 | + | |
102 | + func setupConstraints() { | |
103 | + logoImageView.snp.makeConstraints { make in | |
104 | + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH) | |
105 | + make.leading.trailing.equalToSuperview().inset(143.sizeW) | |
106 | + make.height.equalTo(26.sizeH) | |
107 | + } | |
108 | + | |
109 | + phoneImageView.snp.makeConstraints { make in | |
110 | + make.top.equalTo(logoImageView.snp.bottom).offset(16.sizeH) | |
111 | + make.leading.trailing.equalToSuperview().inset(90.sizeW) | |
112 | + make.height.equalTo(355.sizeH) | |
113 | + } | |
114 | + | |
115 | + zoomedTabImageView.snp.makeConstraints { make in | |
116 | + make.top.equalTo(phoneImageView.snp.top).offset(119.sizeH) | |
117 | + make.leading.equalTo(phoneImageView.snp.leading).offset(91.sizeW) | |
118 | + make.trailing.equalToSuperview().offset(-71) | |
119 | + make.bottom.equalTo(phoneImageView.snp.bottom).offset(-104.sizeH) | |
120 | + } | |
121 | + | |
122 | + infoLabel.snp.makeConstraints { make in | |
123 | + make.top.equalTo(phoneImageView.snp.bottom).offset(16.sizeH) | |
124 | + make.leading.trailing.equalToSuperview().inset(55.sizeW) | |
125 | + } | |
126 | + | |
127 | + advantagesTableView.snp.makeConstraints { make in | |
128 | + make.top.equalTo(infoLabel.snp.bottom).offset(16.sizeH) | |
129 | + make.leading.equalToSuperview().offset(55.sizeW) | |
130 | + make.trailing.equalToSuperview().offset(-92.sizeW) | |
131 | + make.bottom.equalTo(getStartedButton.snp.top).offset(-38.sizeH) | |
132 | + } | |
133 | + | |
134 | + getStartedButton.snp.makeConstraints { make in | |
135 | + make.top.equalTo(advantagesTableView.snp.bottom).offset(24.sizeH) | |
136 | + make.leading.trailing.equalToSuperview().inset(32.sizeW) | |
137 | + make.height.equalTo(40.sizeH) | |
138 | + } | |
139 | + | |
140 | + privacyLabelView.snp.makeConstraints { make in | |
141 | + make.top.equalTo(getStartedButton.snp.bottom).offset(16.sizeH) | |
142 | + make.leading.trailing.equalToSuperview().inset(32.sizeW) | |
143 | + make.bottom.equalTo(safeAreaLayoutGuide).offset(-16.sizeH) | |
144 | + } | |
145 | + | |
146 | + } | |
147 | +} | |
148 | + | |
149 | +//MARK: Gradient | |
150 | +extension PayloadView { | |
151 | + private func gradientSetup() { | |
152 | + getStartedButton.layer.insertSublayer(gradientLayer, at: 0) | |
153 | + gradientLayer.colors = [UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 0.7).cgColor] | |
154 | + gradientLayer.locations = [0.0, 1.0] | |
155 | + } | |
156 | +} | ... | ... |
1 | +// | |
2 | +// RemoveAdvertViewController.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 27.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class RemoveAdvertViewController: UIViewController { | |
11 | + | |
12 | + private let mainView = RemoveAdvertView() | |
13 | + let data = StringConstants.removeAdvertTableViewData | |
14 | + | |
15 | + override func viewDidLoad() { | |
16 | + super.viewDidLoad() | |
17 | + view.backgroundColor = ColorConstants.lightGray | |
18 | + initViewController() | |
19 | + } | |
20 | + | |
21 | + private func initViewController() { | |
22 | + setupTableView() | |
23 | + addTargets() | |
24 | + } | |
25 | + | |
26 | + override func loadView() { | |
27 | + view = mainView | |
28 | + } | |
29 | + | |
30 | + init(){ | |
31 | + super.init(nibName: nil, bundle: nil) | |
32 | + } | |
33 | + | |
34 | + required init?(coder: NSCoder) { | |
35 | + fatalError("init(coder:) has not been implemented") | |
36 | + } | |
37 | +} | |
38 | + | |
39 | + | |
40 | +//MARK: - Table View | |
41 | +extension RemoveAdvertViewController: UITableViewDelegate, UITableViewDataSource { | |
42 | + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
43 | + return data.count | |
44 | + } | |
45 | + | |
46 | + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
47 | + guard let cell = tableView.dequeueReusableCell(withIdentifier: "RemoveAdvertTableViewCell") as? | |
48 | + RemoveAdvertTableViewCell else { | |
49 | + return UITableViewCell() } | |
50 | + | |
51 | + cell.advantagesCellLabel.text = data[indexPath.row] | |
52 | + cell.selectionStyle = .none | |
53 | + | |
54 | + return cell | |
55 | + } | |
56 | + | |
57 | + private func setupTableView() { | |
58 | + mainView.advantagesTableView.dataSource = self | |
59 | + mainView.advantagesTableView.delegate = self | |
60 | + mainView.advantagesTableView.register(RemoveAdvertTableViewCell.self, forCellReuseIdentifier: StringConstants.removeAdvertTableViewCell) | |
61 | + } | |
62 | +} | |
63 | + | |
64 | + | |
65 | +//MARK: - Action | |
66 | +extension RemoveAdvertViewController { | |
67 | + private func addTargets() { | |
68 | + mainView.shieldView.addTarget(self, action: #selector(shieldButtonTapped(_ :)), for: .touchUpInside) | |
69 | + mainView.closeButton.addTarget(self, action: #selector(closeViewController(_ :)), for: .touchUpInside) | |
70 | + } | |
71 | + | |
72 | + @objc | |
73 | + private func shieldButtonTapped(_ sender: UIButton) { | |
74 | + UIView.animate(withDuration: 0.2) { | |
75 | + sender.transform = CGAffineTransform(scaleX: 1.1, y: 1.1) | |
76 | + sender.alpha = 0.7 | |
77 | + } | |
78 | + let userDefaultsAdBlockerValue = CachingManager.shared.isAdBlocking | |
79 | + if userDefaultsAdBlockerValue { | |
80 | + mainView.shieldView.setImage(.shieldInactive, for: .normal) | |
81 | + mainView.tapActionLabel.text = StringConstants.turnOff | |
82 | + CachingManager.shared.isAdBlocking = false | |
83 | + } else { | |
84 | + mainView.shieldView.setImage(.shieldActive, for: .normal) | |
85 | + mainView.tapActionLabel.text = StringConstants.turnOn | |
86 | + CachingManager.shared.isAdBlocking = true | |
87 | + } | |
88 | + UIView.animate(withDuration: 0.2, delay: 0.2) { | |
89 | + sender.transform = .identity | |
90 | + sender.alpha = 1.0 | |
91 | + } | |
92 | + } | |
93 | + | |
94 | + @objc | |
95 | + private func closeViewController(_ sender: UIButton) { | |
96 | + dismiss(animated: true, completion: nil) | |
97 | + } | |
98 | +} | ... | ... |
1 | +// | |
2 | +// RemoveAdvertTableViewCell.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 01.10.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | + | |
11 | +final class RemoveAdvertTableViewCell: UITableViewCell { | |
12 | + let advantagesCellLabel: UILabel = { | |
13 | + let obj = UILabel() | |
14 | + obj.font = FontConstants.regularFont_14 | |
15 | + return obj | |
16 | + }() | |
17 | + | |
18 | + let advantagesCellImage: UIImageView = { | |
19 | + let obj = UIImageView() | |
20 | + let checkmarkImg = UIImage(systemName: "checkmark")?.withTintColor(.blue, renderingMode: .alwaysOriginal) | |
21 | + obj.image = checkmarkImg | |
22 | + obj.contentMode = .scaleToFill | |
23 | + return obj | |
24 | + }() | |
25 | + | |
26 | + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { | |
27 | + super.init(style: style, reuseIdentifier: reuseIdentifier) | |
28 | + setup() | |
29 | + | |
30 | + } | |
31 | + | |
32 | + required init?(coder: NSCoder) { | |
33 | + fatalError("init(coder:) has not been implemented") | |
34 | + } | |
35 | + | |
36 | + func setup() { | |
37 | + contentView.addSubview(advantagesCellLabel) | |
38 | + contentView.addSubview(advantagesCellImage) | |
39 | + backgroundColor = .clear | |
40 | + setupConstraints() | |
41 | + } | |
42 | + | |
43 | + private func setupConstraints() { | |
44 | + advantagesCellImage.snp.makeConstraints { make in | |
45 | + make.top.equalToSuperview().inset(5.sizeH) | |
46 | + make.bottom.equalToSuperview().inset(5.sizeH) | |
47 | + make.leading.equalToSuperview() | |
48 | + make.trailing.equalTo(advantagesCellLabel.snp.leading).offset(-8.sizeW) | |
49 | + } | |
50 | + advantagesCellLabel.snp.makeConstraints { make in | |
51 | + make.top.equalToSuperview().inset(5.sizeH) | |
52 | + make.bottom.equalToSuperview().inset(5.sizeH) | |
53 | + make.leading.equalTo(advantagesCellImage.snp.trailing) | |
54 | + make.trailing.equalToSuperview() | |
55 | + } | |
56 | + } | |
57 | +} | ... | ... |
1 | +// | |
2 | +// RemoveAdvertView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 29.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import SnapKit | |
10 | + | |
11 | +final class RemoveAdvertView: UIView { | |
12 | + | |
13 | + let closeButton: UIButton = { | |
14 | + let obj = UIButton() | |
15 | + obj.setImage(UIImage(systemName: "xmark"), for: .normal) | |
16 | + obj.contentMode = .scaleToFill | |
17 | + obj.tintColor = .gray | |
18 | + return obj | |
19 | + }() | |
20 | + | |
21 | + let shieldView: UIButton = { | |
22 | + let obj = UIButton() | |
23 | + let userDefaultsValue = CachingManager.shared.isAdBlocking | |
24 | + | |
25 | + if userDefaultsValue { | |
26 | + obj.setImage(UIImage(named: "ShieldActive"), for: .normal) | |
27 | + print(userDefaultsValue) | |
28 | + } else { | |
29 | + obj.setImage(UIImage(named: "ShieldInactive"), for: .normal) | |
30 | + print(userDefaultsValue) | |
31 | + } | |
32 | + | |
33 | + obj.contentMode = .scaleAspectFit | |
34 | + return obj | |
35 | + }() | |
36 | + | |
37 | + let gradientLayer = CAGradientLayer() | |
38 | + | |
39 | + let abvertBlockerModeLabel: UILabel = { | |
40 | + let obj = UILabel() | |
41 | + obj.text = StringConstants.advertMode | |
42 | + obj.font = FontConstants.semiboldFont_18 | |
43 | + return obj | |
44 | + }() | |
45 | + | |
46 | + let tapActionLabel: UILabel = { | |
47 | + let obj = UILabel() | |
48 | + obj.text = StringConstants.turnOff | |
49 | + obj.font = FontConstants.semiboldFont_14 | |
50 | + return obj | |
51 | + }() | |
52 | + | |
53 | + let advantagesTableView: UITableView = { | |
54 | + let obj = UITableView() | |
55 | + obj.backgroundColor = .clear | |
56 | + obj.isScrollEnabled = false | |
57 | + obj.separatorStyle = .none | |
58 | + return obj | |
59 | + }() | |
60 | + | |
61 | + let claimOfferLabel: UILabel = { | |
62 | + let obj = UILabel() | |
63 | + obj.text = StringConstants.claimOffer | |
64 | + obj.font = FontConstants.regularFont_12 | |
65 | + return obj | |
66 | + }() | |
67 | + | |
68 | + let priceLabel: UILabel = { | |
69 | + let obj = UILabel() | |
70 | + obj.text = StringConstants.price | |
71 | + obj.font = FontConstants.regularFont_18 | |
72 | + return obj | |
73 | + }() | |
74 | + | |
75 | + let subscribeButton: UIButton = { | |
76 | + let obj = UIButton() | |
77 | + obj.backgroundColor = .systemIndigo | |
78 | + obj.setTitle(StringConstants.subscribe, for: .normal) | |
79 | + obj.titleLabel?.font = FontConstants.semiboldFont_17 | |
80 | + obj.setTitleColor(.white, for: .normal) | |
81 | + obj.layer.cornerRadius = 10 | |
82 | + obj.layer.masksToBounds = true | |
83 | + return obj | |
84 | + }() | |
85 | + | |
86 | + let freeTrialLabel: UILabel = { | |
87 | + let obj = UILabel() | |
88 | + obj.textAlignment = .center | |
89 | + obj.font = FontConstants.semiboldFont_12 | |
90 | + obj.text = StringConstants.freeTrial | |
91 | + return obj | |
92 | + }() | |
93 | + | |
94 | + let discountLabel: UILabel = { | |
95 | + let obj = UILabel() | |
96 | + obj.textAlignment = .center | |
97 | + obj.text = StringConstants.yourDiscount | |
98 | + obj.font = FontConstants.regularFont_12 | |
99 | + return obj | |
100 | + }() | |
101 | + | |
102 | + override init (frame: CGRect) { | |
103 | + super.init(frame: frame) | |
104 | + setup() | |
105 | + } | |
106 | + | |
107 | + override func layoutSubviews() { | |
108 | + super.layoutSubviews() | |
109 | + gradientLayer.frame = subscribeButton.bounds | |
110 | + } | |
111 | + | |
112 | + required init?(coder: NSCoder) { | |
113 | + fatalError("init(coder:) has not been implemented") | |
114 | + } | |
115 | + | |
116 | + private func setup() { | |
117 | + addSubview(closeButton) | |
118 | + addSubview(shieldView) | |
119 | + addSubview(abvertBlockerModeLabel) | |
120 | + addSubview(tapActionLabel) | |
121 | + addSubview(advantagesTableView) | |
122 | + addSubview(claimOfferLabel) | |
123 | + addSubview(priceLabel) | |
124 | + addSubview(subscribeButton) | |
125 | + addSubview(freeTrialLabel) | |
126 | + addSubview(discountLabel) | |
127 | + setupConstraints() | |
128 | + gradientSetup() | |
129 | + } | |
130 | + | |
131 | + func setupConstraints() { | |
132 | + closeButton.snp.makeConstraints { make in | |
133 | + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH) | |
134 | + make.height.equalTo(24.sizeH) | |
135 | + make.trailing.equalToSuperview().inset(16.sizeW) | |
136 | + } | |
137 | + | |
138 | + shieldView.snp.makeConstraints { make in | |
139 | + make.top.equalTo(closeButton.snp.top).offset(8.sizeH) | |
140 | + make.height.equalTo(280.sizeH) | |
141 | + make.leading.trailing.equalToSuperview().inset(47.sizeW) | |
142 | + } | |
143 | + abvertBlockerModeLabel.snp.makeConstraints { make in | |
144 | + make.top.equalTo(shieldView.snp.bottom).offset(16.sizeH) | |
145 | + make.centerX.equalToSuperview() | |
146 | + } | |
147 | + tapActionLabel.snp.makeConstraints { make in | |
148 | + make.top.equalTo(abvertBlockerModeLabel.snp.bottom).offset(8.sizeH) | |
149 | + make.centerX.equalToSuperview() | |
150 | + } | |
151 | + advantagesTableView.snp.makeConstraints { make in | |
152 | + make.top.equalTo(tapActionLabel.snp.bottom).offset(26.sizeH) | |
153 | + make.bottom.equalTo(claimOfferLabel.snp.top).offset(-24.sizeH) | |
154 | + make.leading.equalToSuperview().offset(80.sizeW) | |
155 | + make.trailing.equalToSuperview().offset(-86.sizeW) | |
156 | + } | |
157 | + claimOfferLabel.snp.makeConstraints { make in | |
158 | + make.bottom.equalTo(priceLabel.snp.top).offset(-4.sizeH) | |
159 | + make.centerX.equalToSuperview() | |
160 | + } | |
161 | + priceLabel.snp.makeConstraints { make in | |
162 | + make.bottom.equalTo(subscribeButton.snp.top).offset(-16.sizeH) | |
163 | + make.centerX.equalToSuperview() | |
164 | + } | |
165 | + subscribeButton.snp.makeConstraints { make in | |
166 | + make.bottom.equalTo(freeTrialLabel.snp.top).offset(-16.sizeH) | |
167 | + make.leading.trailing.equalToSuperview().inset(32.sizeW) | |
168 | + make.height.equalTo(40.sizeH) | |
169 | + } | |
170 | + freeTrialLabel.snp.makeConstraints { make in | |
171 | + make.bottom.equalTo(discountLabel.snp.top).offset(-8.sizeH) | |
172 | + make.centerX.equalToSuperview() | |
173 | + } | |
174 | + discountLabel.snp.makeConstraints { make in | |
175 | + make.centerX.equalToSuperview() | |
176 | + make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-24.sizeH) | |
177 | + } | |
178 | + } | |
179 | +} | |
180 | + | |
181 | +//MARK: gradient | |
182 | +extension RemoveAdvertView { | |
183 | + private func gradientSetup() { | |
184 | + subscribeButton.layer.insertSublayer(gradientLayer, at: 0) | |
185 | + gradientLayer.colors = [UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 0.7).cgColor] | |
186 | + gradientLayer.locations = [0.0, 1.0] | |
187 | + } | |
188 | +} | ... | ... |
1 | +// | |
2 | +// SearchResultViewColroller.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 05.10.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import WebKit | |
10 | + | |
11 | +final class SearchResultViewController: UIViewController { | |
12 | + let mainView = SearchResultView() | |
13 | + var searchLink: String | |
14 | + | |
15 | + init(searchLink: String) { | |
16 | + self.searchLink = searchLink | |
17 | + super.init(nibName: nil, bundle: nil) | |
18 | + } | |
19 | + | |
20 | + required init?(coder: NSCoder) { | |
21 | + fatalError("init(coder:) has not been implemented") | |
22 | + } | |
23 | + | |
24 | + override func loadView() { | |
25 | + view = mainView | |
26 | + } | |
27 | + | |
28 | + override func viewDidLoad() { | |
29 | + super.viewDidLoad() | |
30 | + initViewController() | |
31 | + } | |
32 | + | |
33 | + private func initViewController() { | |
34 | + view.backgroundColor = ColorConstants.lightGray | |
35 | + urlChecker(searchLink) | |
36 | + setupAdBlocker() | |
37 | + } | |
38 | + | |
39 | + override func viewIsAppearing(_ animated: Bool) { | |
40 | + navigationController?.isNavigationBarHidden = true | |
41 | + } | |
42 | +} | |
43 | + | |
44 | +extension SearchResultViewController { | |
45 | + func urlChecker(_ url: String) { | |
46 | + let request = URLRequest(url: URL(string: url) ?? URL(fileURLWithPath: "")) | |
47 | + mainView.searchResultView.load(request) | |
48 | + } | |
49 | +} | |
50 | + | |
51 | + | |
52 | +//MARK: AdBlocker | |
53 | +extension SearchResultViewController { | |
54 | + func setupAdBlocker() { | |
55 | + let userDefaultsValue = CachingManager.shared.isAdBlocking | |
56 | + if userDefaultsValue { | |
57 | + WKContentRuleListStore.default().getAvailableContentRuleListIdentifiers { res in | |
58 | +// if res?.isEmpty ?? true { | |
59 | + if let url = Bundle.main.url(forResource: "blockerList", withExtension: "json"), | |
60 | + let str = try? String(contentsOf: url) { | |
61 | + WKContentRuleListStore.default().compileContentRuleList(forIdentifier: "blockerList", encodedContentRuleList: str) { list, error in | |
62 | + if let list { | |
63 | + self.mainView.searchResultView.configuration.userContentController.add(list) | |
64 | + } | |
65 | + } | |
66 | + } | |
67 | +// } | |
68 | + } | |
69 | + } else { | |
70 | + WKContentRuleListStore.default().getAvailableContentRuleListIdentifiers { res in | |
71 | + if res != nil { | |
72 | + WKContentRuleListStore.default().removeContentRuleList(forIdentifier: "blockerList") { error in | |
73 | + if let error { | |
74 | + print(error) | |
75 | + } | |
76 | + } | |
77 | + } | |
78 | + } | |
79 | + } | |
80 | + } | |
81 | +} | ... | ... |
1 | +// | |
2 | +// SearchResultView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 05.10.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import WebKit | |
10 | + | |
11 | +final class SearchResultView: UIView { | |
12 | + let searchResultView: WKWebView = { | |
13 | +// let userDefaultsValue = CachingManager.shared.isAdBlocking | |
14 | +// if userDefaultsValue { | |
15 | +// let configuration = WKWebViewConfiguration() | |
16 | +// let contentController = WKUserContentController() | |
17 | +// let url = Bundle.main.url(forResource: "blockerList", withExtension: "json")?.absoluteString ?? "" | |
18 | +// contentController.addUserScript(WKUserScript(source: url, injectionTime: .atDocumentStart, forMainFrameOnly: false)) | |
19 | +// configuration.userContentController = contentController | |
20 | +// let obj = WKWebView(frame: .zero, configuration: configuration) | |
21 | +// obj.allowsBackForwardNavigationGestures = true | |
22 | +// obj.allowsLinkPreview = true | |
23 | +// return obj | |
24 | +// } else { | |
25 | + let obj = WKWebView() | |
26 | + obj.allowsBackForwardNavigationGestures = true | |
27 | + obj.allowsLinkPreview = true | |
28 | + return obj | |
29 | + // } | |
30 | + }() | |
31 | + | |
32 | + override init(frame: CGRect) { | |
33 | + super.init(frame: frame) | |
34 | + setup() | |
35 | + } | |
36 | + | |
37 | + | |
38 | + required init?(coder: NSCoder) { | |
39 | + fatalError("init(coder:) has not been implemented") | |
40 | + } | |
41 | + | |
42 | + private func setup() { | |
43 | + addSubview(searchResultView) | |
44 | + setupConstaraints() | |
45 | + backgroundColor = .white | |
46 | + } | |
47 | + | |
48 | + private func setupConstaraints() { | |
49 | + searchResultView.snp.makeConstraints { make in | |
50 | + make.top.equalTo(safeAreaLayoutGuide.snp.top) | |
51 | + make.leading.trailing.equalToSuperview() | |
52 | + make.bottom.equalToSuperview() | |
53 | + } | |
54 | + } | |
55 | +} | |
56 | + | ... | ... |
1 | +// | |
2 | +// SearchingViewController.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 29.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class SearchingViewController: UIViewController { | |
11 | + let mainView = SearchingView() | |
12 | + var dataForReq: [String] { | |
13 | + didSet { | |
14 | + mainView.searchTableView.reloadData() | |
15 | + } | |
16 | + } | |
17 | + var searchCell: ((UITableViewCell) -> Void)? | |
18 | + | |
19 | + init(dataForReq: [String]) { | |
20 | + self.dataForReq = dataForReq | |
21 | + super.init(nibName: nil, bundle: nil) | |
22 | + } | |
23 | + | |
24 | + required init?(coder: NSCoder) { | |
25 | + fatalError("init(coder:) has not been implemented") | |
26 | + } | |
27 | + | |
28 | + override func loadView() { | |
29 | + view = mainView | |
30 | + } | |
31 | + | |
32 | + override func viewDidLoad() { | |
33 | + super.viewDidLoad() | |
34 | + view.backgroundColor = ColorConstants.lightGray | |
35 | + initViewController() | |
36 | + } | |
37 | + | |
38 | + private func initViewController() { | |
39 | + setupTableView() | |
40 | + } | |
41 | +} | |
42 | + | |
43 | +extension SearchingViewController: UITableViewDelegate, UITableViewDataSource { | |
44 | + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
45 | + return dataForReq.count | |
46 | + } | |
47 | + | |
48 | + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
49 | + guard let cell = tableView.dequeueReusableCell(withIdentifier: "SearchingTableViewCell", for: indexPath) as? SearchingTableViewCell else { | |
50 | + return SearchingTableViewCell() | |
51 | + } | |
52 | + let searchCellData = dataForReq[indexPath.row] | |
53 | + cell.model = searchCellData | |
54 | + return cell | |
55 | + } | |
56 | + | |
57 | + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | |
58 | + guard let tappedCell = tableView.cellForRow(at: indexPath) else { return } | |
59 | + searchCell?(tappedCell) | |
60 | + } | |
61 | + | |
62 | + func setupTableView() { | |
63 | + mainView.searchTableView.dataSource = self | |
64 | + mainView.searchTableView.delegate = self | |
65 | + mainView.searchTableView.register(SearchingTableViewCell.self, forCellReuseIdentifier: StringConstants.searchTableViewCell) | |
66 | + } | |
67 | +} | |
68 | + | ... | ... |
1 | +// | |
2 | +// SearchingTableViewCell.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 29.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +class SearchingTableViewCell: UITableViewCell { | |
11 | + var model: String? { | |
12 | + didSet { | |
13 | + handleUI() | |
14 | + } | |
15 | + } | |
16 | + | |
17 | + var searchImage: UIImageView = { | |
18 | + let obj = UIImageView() | |
19 | + obj.image = UIImage(systemName: "magnifyingglass") | |
20 | + obj.tintColor = .gray | |
21 | + return obj | |
22 | + }() | |
23 | + | |
24 | + var searchLabel: UILabel = { | |
25 | + let obj = UILabel() | |
26 | + obj.font = FontConstants.regularFont_14 | |
27 | + return obj | |
28 | + }() | |
29 | + | |
30 | + var siteLogoImage: UIImageView = { | |
31 | + let obj = UIImageView() | |
32 | + return obj | |
33 | + }() | |
34 | + | |
35 | + var linkImage: UIImageView = { | |
36 | + let obj = UIImageView() | |
37 | + obj.image = UIImage(systemName: "arrow.up.left") | |
38 | + obj.tintColor = .gray | |
39 | + return obj | |
40 | + }() | |
41 | + | |
42 | + | |
43 | + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { | |
44 | + super.init(style: style, reuseIdentifier: reuseIdentifier) | |
45 | + setup() | |
46 | + } | |
47 | + | |
48 | + required init?(coder: NSCoder) { | |
49 | + fatalError("init(coder:) has not been implemented") | |
50 | + } | |
51 | + | |
52 | + func setup() { | |
53 | + contentView.addSubview(searchImage) | |
54 | + contentView.addSubview(searchLabel) | |
55 | + contentView.addSubview(siteLogoImage) | |
56 | + contentView.addSubview(linkImage) | |
57 | + setupConstraints() | |
58 | + } | |
59 | + | |
60 | + private func setupConstraints() { | |
61 | + searchImage.snp.makeConstraints { make in | |
62 | + make.top.equalToSuperview().offset(8.sizeH) | |
63 | + make.leading.equalToSuperview().offset(8.sizeW) | |
64 | + make.bottom.equalToSuperview().offset(-8.sizeH) | |
65 | + } | |
66 | + searchLabel.snp.makeConstraints { make in | |
67 | + make.top.equalToSuperview().inset(8.sizeH) | |
68 | + make.leading.equalTo(searchImage.snp.trailing).offset(8.sizeW) | |
69 | + } | |
70 | + siteLogoImage.snp.makeConstraints { make in | |
71 | + make.top.equalToSuperview().inset(8.sizeH) | |
72 | + make.height.width.equalTo(18.sizeH) | |
73 | + } | |
74 | + linkImage.snp.makeConstraints { make in | |
75 | + make.top.equalToSuperview().inset(8.sizeH) | |
76 | + make.leading.equalTo(siteLogoImage.snp.trailing).offset(8.sizeW) | |
77 | + make.trailing.equalToSuperview().inset(8.sizeW) | |
78 | + } | |
79 | + } | |
80 | +} | |
81 | + | |
82 | +extension SearchingTableViewCell { | |
83 | + private func handleUI() { | |
84 | + searchLabel.text = model | |
85 | +// if model?.siteLogo != UIImage() { | |
86 | +// siteLogoImage.image = model?.siteLogo | |
87 | +// } else { | |
88 | +// siteLogoImage.image = UIImage() | |
89 | +// } | |
90 | + } | |
91 | +} | ... | ... |
1 | +// | |
2 | +// SearchingView.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 29.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | + | |
10 | +final class SearchingView: UIView, UITextFieldDelegate { | |
11 | + let searchingButton: UIButton = { | |
12 | + let obj = UIButton() | |
13 | + obj.setImage(UIImage(systemName: "arrow.left"), for: .normal) | |
14 | + return obj | |
15 | + }() | |
16 | + | |
17 | + let searchingLabel: UILabel = { | |
18 | + let obj = UILabel() | |
19 | + obj.text = "Searching" | |
20 | + obj.font = FontConstants.semiboldFont_18 | |
21 | + return obj | |
22 | + }() | |
23 | + | |
24 | + let searchTableView: UITableView = { | |
25 | + let obj = UITableView() | |
26 | + obj.backgroundColor = .clear | |
27 | + obj.separatorStyle = .none | |
28 | + return obj | |
29 | + }() | |
30 | + | |
31 | + override init(frame: CGRect) { | |
32 | + super.init(frame: frame) | |
33 | + setup() | |
34 | + } | |
35 | + | |
36 | + required init?(coder: NSCoder) { | |
37 | + fatalError("init(coder:) has not been implemented") | |
38 | + } | |
39 | + | |
40 | + private func setup() { | |
41 | + addSubview(searchingButton) | |
42 | + addSubview(searchingLabel) | |
43 | + addSubview(searchTableView) | |
44 | + setupConstaraints() | |
45 | + backgroundColor = .white | |
46 | + } | |
47 | + | |
48 | + private func setupConstaraints() { | |
49 | + searchingButton.snp.makeConstraints { make in | |
50 | + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH) | |
51 | + make.leading.equalToSuperview().offset(16.sizeW) | |
52 | + make.height.equalTo(24.sizeH) | |
53 | + } | |
54 | + | |
55 | + searchingLabel.snp.makeConstraints { make in | |
56 | + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH) | |
57 | + make.leading.equalTo(searchingButton.snp.trailing).offset(109.sizeW) | |
58 | + make.trailing.equalToSuperview().offset(-138.sizeW) | |
59 | + } | |
60 | + | |
61 | + searchTableView.snp.makeConstraints { make in | |
62 | + make.top.equalTo(searchingLabel.snp.bottom).offset(16.sizeH) | |
63 | + make.leading.trailing.equalToSuperview().inset(16.sizeW) | |
64 | + make.bottom.equalToSuperview()/*.offset(-16.sizeH)*/ | |
65 | + } | |
66 | + } | |
67 | +} | |
68 | + | ... | ... |
1 | +// | |
2 | +// SettingController.swift | |
3 | +// browser | |
4 | +// | |
5 | +// Created by Artem Talko on 26.09.2023. | |
6 | +// | |
7 | + | |
8 | +import UIKit | |
9 | +import MessageUI | |
10 | + | |
11 | +final class SettingViewController: UIViewController { | |
12 | + private let mainView = SettingView() | |
13 | + private let param = StringConstants.settingViewControllerTableViewData | |
14 | + init() { | |
15 | + super.init(nibName: nil, bundle: nil) | |
16 | + } | |
17 | + | |
18 | + required init?(coder: NSCoder) { | |
19 | + fatalError("init(coder:) has not been implemented") | |
20 | + } | |
21 | + | |
22 | + override func loadView() { | |
23 | + view = mainView | |
24 | + } | |
25 | + | |
26 | + override func viewDidLoad() { | |
27 | + super.viewDidLoad() | |
28 | + view.backgroundColor = .white | |
29 | + initViewController() | |
30 | + } | |
31 | + | |
32 | + private func initViewController() { | |
33 | + navigationController?.isNavigationBarHidden = false | |
34 | + setupSettingTableView() | |
35 | + addTargets() | |
36 | + } | |
37 | +} | |
38 | + | |
39 | + | |
40 | +//MARK: SettingTableView | |
41 | +extension SettingViewController: UITableViewDelegate, UITableViewDataSource { | |
42 | + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
43 | + return param.count | |
44 | + } | |
45 | + | |
46 | + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
47 | + guard let cell = tableView.dequeueReusableCell(withIdentifier: "SettingTableViewCell", for: indexPath) as? SettingTableViewCell | |
48 | + else { return UITableViewCell() } | |
49 | + let info = param[indexPath.item] | |
50 | + cell.settingTableViewLabel.text = info | |
51 | + cell.selectionStyle = .none | |
52 | + return cell | |
53 | + } | |
54 | + | |
55 | + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { | |
56 | + return 60.0 | |
57 | + } | |
58 | + | |
59 | + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | |
60 | + let index = indexPath.row | |
61 | + cellPresshandler(index) | |
62 | + } | |
63 | +} | |
64 | + | |
65 | + | |
66 | +//MARK: - Helpers | |
67 | +extension SettingViewController { | |
68 | + private func setupSettingTableView() { | |
69 | + mainView.settingTableView.delegate = self | |
70 | + mainView.settingTableView.dataSource = self | |
71 | + mainView.settingTableView.register(SettingTableViewCell.self, forCellReuseIdentifier: StringConstants.settingTableViewCell) | |
72 | + } | |
73 | + | |
74 | + private func setupMessage() { | |
75 | + guard MFMailComposeViewController.canSendMail() else { | |
76 | + return | |
77 | + } | |
78 | + let composer = MFMailComposeViewController() | |
79 | + composer.mailComposeDelegate = self | |
80 | + composer.setToRecipients(["test@gmail.com"]) | |
81 | + composer.setSubject("Browser") | |
82 | + present(composer, animated: true, completion: nil) | |
83 | + } | |
84 | + | |
85 | + private func cellPresshandler(_ index: Int) { | |
86 | + switch index { | |
87 | + case 0: | |
88 | + let privacyViewController = PrivacyViewController() | |
89 | + presentViewController(privacyViewController) | |
90 | + case 1: | |
91 | + let termsViewController = TermsViewController() | |
92 | + presentViewController(termsViewController) | |
93 | + case 2: | |
94 | + shareButtonPressed() | |
95 | + case 3: | |
96 | + break | |
97 | + case 4: | |
98 | + setupMessage() | |
99 | + default: | |
100 | + break | |
101 | + } | |
102 | + } | |
103 | +} | |
104 | + | |
105 | +//MARK: - Action | |
106 | +extension SettingViewController { | |
107 | + func addTargets() { | |
108 | + mainView.backButton.addTarget(self, action: #selector(closeViewController(_ :)), for: .touchUpInside) | |
109 | + } | |
110 | + | |
111 | + @objc | |
112 | + private func closeViewController(_ sender: UIButton) { | |
113 | + dismiss(animated: true, completion: nil) | |
114 | + } | |
115 | + | |
116 | + private func shareButtonPressed() { | |
117 | + let items = [URL(string: URLConstants.shareAppLink)] | |
118 | + let shareView = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil) | |
119 | + present(shareView, animated: true) | |
120 | + } | |
121 | + | |
122 | + private func presentViewController(_ viewController: UIViewController) { | |
123 | + viewController.modalPresentationStyle = .fullScreen | |
124 | + present(viewController, animated: true) | |
125 | + } | |
126 | + | |
127 | +} | |
128 | + | |
129 | +//MARK: Mail helper | |
130 | +extension SettingViewController: MFMailComposeViewControllerDelegate { | |
131 | + func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { | |
132 | + if let _ = error { | |
133 | + controller.dismiss(animated: true) | |
134 | + } | |
135 | + switch result { | |
136 | + case .cancelled: | |
137 | + print("cancelled") | |
138 | + case .saved: | |
139 | + print("saved") | |
140 | + case .sent: | |
141 | + print("send") | |
142 | + case .failed: | |
143 | + print("fail") | |
144 | + @unknown default: | |
145 | + print("error!") | |
146 | + } | |
147 | + | |
148 | + controller.dismiss(animated: true) | |
149 | + } | |
150 | +} | ... | ... |
Please
register
or
login
to post a comment