diff --git a/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents b/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents
index aae7f5927..a6208aaeb 100644
--- a/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents
+++ b/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents
@@ -10,6 +10,7 @@
+
@@ -32,7 +33,7 @@
-
+
\ No newline at end of file
diff --git a/CoreDataStack/Entity/MastodonUser.swift b/CoreDataStack/Entity/MastodonUser.swift
index 09b9f1604..718a589a4 100644
--- a/CoreDataStack/Entity/MastodonUser.swift
+++ b/CoreDataStack/Entity/MastodonUser.swift
@@ -18,6 +18,9 @@ final public class MastodonUser: NSManagedObject {
@NSManaged public private(set) var acct: String
@NSManaged public private(set) var username: String
@NSManaged public private(set) var displayName: String?
+ @NSManaged public private(set) var avatar: String
+ @NSManaged public private(set) var avatarStatic: String
+
@NSManaged public private(set) var createdAt: Date
@NSManaged public private(set) var updatedAt: Date
@@ -42,6 +45,8 @@ extension MastodonUser {
user.acct = property.acct
user.username = property.username
user.displayName = property.displayName
+ user.avatar = property.avatar
+ user.avatarStatic = property.avatarStatic
user.createdAt = property.createdAt
user.updatedAt = property.networkDate
@@ -60,6 +65,8 @@ extension MastodonUser {
public let acct: String
public let username: String
public let displayName: String?
+ public let avatar: String
+ public let avatarStatic: String
public let createdAt: Date
public let networkDate: Date
@@ -70,6 +77,8 @@ extension MastodonUser {
acct: String,
username: String,
displayName: String?,
+ avatar:String,
+ avatarStatic:String,
createdAt: Date,
networkDate: Date
) {
@@ -81,6 +90,8 @@ extension MastodonUser {
self.displayName = displayName.flatMap { displayName in
return displayName.isEmpty ? nil : displayName
}
+ self.avatar = avatar
+ self.avatarStatic = avatarStatic
self.createdAt = createdAt
self.networkDate = networkDate
}
diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj
index 7e9ca0e89..bfbf71607 100644
--- a/Mastodon.xcodeproj/project.pbxproj
+++ b/Mastodon.xcodeproj/project.pbxproj
@@ -22,6 +22,8 @@
2D76319F25C1521200929FB9 /* TimelineSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76319E25C1521200929FB9 /* TimelineSection.swift */; };
2D7631A825C1535600929FB9 /* TimelinePostTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631A725C1535600929FB9 /* TimelinePostTableViewCell.swift */; };
2D7631B325C159F700929FB9 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631B225C159F700929FB9 /* Item.swift */; };
+ 2D9BB87B25C3FEF200678AB6 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D9BB87A25C3FEF200678AB6 /* String.swift */; };
+ 2DF123A725C3B0210020F248 /* ActiveLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF123A625C3B0210020F248 /* ActiveLabel.swift */; };
3533495136D843E85211E3E2 /* Pods_Mastodon_MastodonUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B4523A7981F1044DE89C21 /* Pods_Mastodon_MastodonUITests.framework */; };
5D526FE225BE9AC400460CB9 /* MastodonSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 5D526FE125BE9AC400460CB9 /* MastodonSDK */; };
5E44BF88AD33646E64727BCF /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */; };
@@ -129,6 +131,8 @@
2D76319E25C1521200929FB9 /* TimelineSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineSection.swift; sourceTree = ""; };
2D7631A725C1535600929FB9 /* TimelinePostTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinePostTableViewCell.swift; sourceTree = ""; };
2D7631B225C159F700929FB9 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; };
+ 2D9BB87A25C3FEF200678AB6 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; };
+ 2DF123A625C3B0210020F248 /* ActiveLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveLabel.swift; sourceTree = ""; };
2E1F6A67FDF9771D3E064FDC /* Pods-Mastodon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.debug.xcconfig"; sourceTree = ""; };
459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.debug.xcconfig"; sourceTree = ""; };
602D783BEC22881EBAD84419 /* Pods_Mastodon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -532,6 +536,8 @@
DB8AF55C25C138B7002E6C99 /* UIViewController.swift */,
2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */,
2D46976325C2A71500CF4AA9 /* UIIamge.swift */,
+ 2DF123A625C3B0210020F248 /* ActiveLabel.swift */,
+ 2D9BB87A25C3FEF200678AB6 /* String.swift */,
);
path = Extension;
sourceTree = "";
@@ -664,6 +670,7 @@
TargetAttributes = {
DB427DD125BAA00100D1B89D = {
CreatedOnToolsVersion = 12.4;
+ LastSwiftMigration = 1220;
};
DB427DE725BAA00100D1B89D = {
CreatedOnToolsVersion = 12.4;
@@ -879,9 +886,11 @@
2D7631B325C159F700929FB9 /* Item.swift in Sources */,
2D61335E25C1894B00CAE157 /* APIService.swift in Sources */,
DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */,
+ 2D9BB87B25C3FEF200678AB6 /* String.swift in Sources */,
2D152A8C25C295CC009AA50C /* TimelinePostView.swift in Sources */,
2D61335825C188A000CAE157 /* APIService+Persist+Timeline.swift in Sources */,
DB8AF52F25C13561002E6C99 /* DocumentStore.swift in Sources */,
+ 2DF123A725C3B0210020F248 /* ActiveLabel.swift in Sources */,
2D76316B25C14D4C00929FB9 /* PublicTimelineViewModel.swift in Sources */,
2D46975E25C2A54100CF4AA9 /* NSLayoutConstraint.swift in Sources */,
2D46976425C2A71500CF4AA9 /* UIIamge.swift in Sources */,
@@ -1126,6 +1135,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 7LFDZ96332;
@@ -1137,6 +1147,7 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.Mastodon;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -1148,6 +1159,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 7LFDZ96332;
diff --git a/Mastodon/Diffiable/Section/TimelineSection.swift b/Mastodon/Diffiable/Section/TimelineSection.swift
index e9fc68be8..49345c177 100644
--- a/Mastodon/Diffiable/Section/TimelineSection.swift
+++ b/Mastodon/Diffiable/Section/TimelineSection.swift
@@ -47,7 +47,8 @@ extension TimelineSection {
) {
cell.timelinePostView.nameLabel.text = toot.author.displayName
cell.timelinePostView.usernameLabel.text = toot.author.username
-
+ cell.timelinePostView.avatarImageView.af.setImage(withURL: URL(string: toot.author.avatar)!)
+ cell.timelinePostView.activeTextLabel.config(content: toot.content)
}
}
diff --git a/Mastodon/Extension/ActiveLabel.swift b/Mastodon/Extension/ActiveLabel.swift
new file mode 100644
index 000000000..8423e8b97
--- /dev/null
+++ b/Mastodon/Extension/ActiveLabel.swift
@@ -0,0 +1,48 @@
+//
+// ActiveLabel.swift
+// Mastodon
+//
+// Created by sxiaojian on 2021/1/29.
+//
+
+import UIKit
+import Foundation
+import ActiveLabel
+
+
+extension ActiveLabel {
+
+ enum Style {
+ case `default`
+ case timelineHeaderView
+ }
+
+ convenience init(style: Style) {
+ self.init()
+
+ switch style {
+ case .default:
+// urlMaximumLength = 30
+ font = .preferredFont(forTextStyle: .body)
+ textColor = UIColor.label.withAlphaComponent(0.8)
+ case .timelineHeaderView:
+ font = .preferredFont(forTextStyle: .footnote)
+ textColor = .secondaryLabel
+ }
+
+ numberOfLines = 0
+ mentionColor = UIColor.yellow
+ hashtagColor = UIColor.blue
+ URLColor = UIColor.red
+ text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+ }
+
+}
+
+extension ActiveLabel {
+ func config(content:String) {
+ let html = content.replacingOccurrences(of: "
", with: "
").replacingOccurrences(of: "
", with: "").replacingOccurrences(of: "
", with: "")
+ text = html.toPlainText()
+ }
+}
+
diff --git a/Mastodon/Extension/String.swift b/Mastodon/Extension/String.swift
new file mode 100644
index 000000000..b583d3f69
--- /dev/null
+++ b/Mastodon/Extension/String.swift
@@ -0,0 +1,39 @@
+//
+// String.swift
+// Mastodon
+//
+// Created by sxiaojian on 2021/1/29.
+//
+
+import Foundation
+extension String {
+ public func pregReplace(pattern: String, with: String, options: NSRegularExpression.Options = []) -> String {
+ // swiftlint:disable force_try
+ let regex = try! NSRegularExpression(pattern: pattern, options: options)
+ return regex.stringByReplacingMatches(in: self, options: [], range: NSRange(location: 0, length: nsLength), withTemplate: with)
+ }
+}
+extension String {
+ public var nsLength: Int {
+ let string_NS = self as NSString
+ return string_NS.length
+ }
+}
+extension String {
+ func toPlainText() -> String {
+ return self.pregReplace(pattern: "", with: "\n")
+ .replacingOccurrences(of: "", with: "\n\n")
+ .pregReplace(pattern: "<.+?>", with: "")
+ .replacingOccurrences(of: "<", with: "<")
+ .replacingOccurrences(of: ">", with: ">")
+ .replacingOccurrences(of: "'", with: "'")
+ .replacingOccurrences(of: """, with: "\"")
+ .replacingOccurrences(of: "&", with: "&")
+ }
+}
+extension String {
+ func string(in nsrange: NSRange) -> String? {
+ guard let range = Range(nsrange, in: self) else { return nil }
+ return String(self[range])
+ }
+}
diff --git a/Mastodon/Scene/HomeViewController.swift b/Mastodon/Scene/HomeViewController.swift
index 6a533558d..db2340f1d 100644
--- a/Mastodon/Scene/HomeViewController.swift
+++ b/Mastodon/Scene/HomeViewController.swift
@@ -22,6 +22,6 @@ extension HomeViewController {
title = "Home"
view.backgroundColor = .systemBackground
+
}
-
}
diff --git a/Mastodon/Scene/Share/View/Content/TimelinePostView.swift b/Mastodon/Scene/Share/View/Content/TimelinePostView.swift
index 12ba1ccc5..44443361c 100644
--- a/Mastodon/Scene/Share/View/Content/TimelinePostView.swift
+++ b/Mastodon/Scene/Share/View/Content/TimelinePostView.swift
@@ -7,6 +7,7 @@
import UIKit
import AVKit
+import ActiveLabel
final class TimelinePostView: UIView {
@@ -41,6 +42,7 @@ final class TimelinePostView: UIView {
let mainContainerStackView = UIStackView()
+ let activeTextLabel = ActiveLabel(style: .default)
override init(frame: CGRect) {
super.init(frame: frame)
@@ -107,6 +109,15 @@ extension TimelinePostView {
usernameLabel.setContentCompressionResistancePriority(.defaultHigh - 1, for: .horizontal)
dateLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
dateLabel.setContentCompressionResistancePriority(.required - 2, for: .horizontal)
+
+ // main container: [text | image / video | quote | geo]
+ tweetContainerStackView.addArrangedSubview(mainContainerStackView)
+ mainContainerStackView.axis = .vertical
+ mainContainerStackView.spacing = 8
+ activeTextLabel.translatesAutoresizingMaskIntoConstraints = false
+ mainContainerStackView.addArrangedSubview(activeTextLabel)
+
+ activeTextLabel.setContentCompressionResistancePriority(.required - 2, for: .vertical)
}
diff --git a/Mastodon/Service/Persist/APIService+Persist+Timeline.swift b/Mastodon/Service/Persist/APIService+Persist+Timeline.swift
index b43ee1010..c2d1602d5 100644
--- a/Mastodon/Service/Persist/APIService+Persist+Timeline.swift
+++ b/Mastodon/Service/Persist/APIService+Persist+Timeline.swift
@@ -25,7 +25,7 @@ extension APIService.Persist {
return managedObjectContext.performChanges {
let toots = response.value
let _ = toots.map {
- let userProperty = MastodonUser.Property(id: $0.account.id, domain: domain, acct: $0.account.acct, username: $0.account.username, displayName: $0.account.displayName, createdAt: $0.createdAt, networkDate: $0.createdAt)
+ let userProperty = MastodonUser.Property(id: $0.account.id, domain: domain, acct: $0.account.acct, username: $0.account.username, displayName: $0.account.displayName,avatar: $0.account.avatar,avatarStatic: $0.account.avatarStatic, createdAt: $0.createdAt, networkDate: $0.createdAt)
let author = MastodonUser.insert(into: managedObjectContext, property: userProperty)
let tootProperty = Toot.Property(id: $0.id, domain: domain, content: $0.content, createdAt: $0.createdAt, networkDate: $0.createdAt)
Toot.insert(into: managedObjectContext, property: tootProperty, author: author)
diff --git a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Account.swift b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Account.swift
index f794dabb9..6f167730e 100644
--- a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Account.swift
+++ b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Account.swift
@@ -34,9 +34,9 @@ extension Mastodon.Entity {
public let displayName: String
public let note: String
public let avatar: String
- public let avatarStatic: String?
+ public let avatarStatic: String
public let header: String
- public let headerStatic: String?
+ public let headerStatic: String
public let locked: Bool
public let emojis: [Emoji]?
public let discoverable: Bool?
diff --git a/Podfile b/Podfile
index 32659fa54..dee59e4d9 100644
--- a/Podfile
+++ b/Podfile
@@ -9,7 +9,7 @@ target 'Mastodon' do
# misc
pod 'SwiftGen', '~> 6.4.0'
pod 'DateToolsSwift', '~> 5.0.0'
-
+ pod 'ActiveLabel', git: 'https://github.com/ReticentJohn/ActiveLabel.swift.git', branch: 'master'
target 'MastodonTests' do
inherit! :search_paths
# Pods for testing
diff --git a/Podfile.lock b/Podfile.lock
index da5a99e0e..94ee59e39 100644
--- a/Podfile.lock
+++ b/Podfile.lock
@@ -1,8 +1,10 @@
PODS:
+ - ActiveLabel (1.1.0)
- DateToolsSwift (5.0.0)
- SwiftGen (6.4.0)
DEPENDENCIES:
+ - ActiveLabel (from `https://github.com/ReticentJohn/ActiveLabel.swift.git`, branch `master`)
- DateToolsSwift (~> 5.0.0)
- SwiftGen (~> 6.4.0)
@@ -11,10 +13,21 @@ SPEC REPOS:
- DateToolsSwift
- SwiftGen
+EXTERNAL SOURCES:
+ ActiveLabel:
+ :branch: master
+ :git: https://github.com/ReticentJohn/ActiveLabel.swift.git
+
+CHECKOUT OPTIONS:
+ ActiveLabel:
+ :commit: 01dd31cbbd1b3fec33b0c024b011e6b932794eff
+ :git: https://github.com/ReticentJohn/ActiveLabel.swift.git
+
SPEC CHECKSUMS:
+ ActiveLabel: 5e3f4de79a1952d4604b845a0610d4776e4b82b3
DateToolsSwift: 4207ada6ad615d8dc076323d27037c94916dbfa6
SwiftGen: 67860cc7c3cfc2ed25b9b74cfd55495fc89f9108
-PODFILE CHECKSUM: 5a58ccfd113912468e008313e1c91ed51b7cba20
+PODFILE CHECKSUM: 7fd5233d3180e2f7f67c96a28abbc20c6eddac93
COCOAPODS: 1.10.1