Skip to content

Commit

Permalink
Merge pull request #132 from TwidereProject/feature/multi-window
Browse files Browse the repository at this point in the history
Add multi-window support for iPad
  • Loading branch information
MainasuK committed May 11, 2023
2 parents e1ebf42 + 614a8c5 commit d5c9371
Show file tree
Hide file tree
Showing 56 changed files with 747 additions and 778 deletions.
2 changes: 1 addition & 1 deletion NotificationService/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleVersion</key>
<string>125</string>
<string>128</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
2 changes: 1 addition & 1 deletion ShareExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<key>CFBundleVersion</key>
<string>125</string>
<string>128</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
Expand Down
2 changes: 1 addition & 1 deletion TwidereSDK/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ let package = Package(
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "1.6.0"),
.package(url: "https://github.com/tid-kijyun/Kanna.git", from: "5.2.7"),
.package(url: "https://github.com/JohnSundell/CollectionConcurrencyKit.git", from: "0.2.0"),
.package(url: "https://github.com/TwidereProject/TwitterSDK.git", exact: "0.4.0"),
.package(url: "https://github.com/TwidereProject/TwitterSDK.git", exact: "0.7.0"),
.package(name: "ArkanaKeys", path: "../dependencies/ArkanaKeys"),
.package(name: "CoverFlowStackLayout", path: "../CoverFlowStackLayout"),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@
<attribute name="emojis" optional="YES" attributeType="Binary"/>
<attribute name="entities" optional="YES" attributeType="Binary"/>
<attribute name="id" attributeType="String"/>
<attribute name="isMediaSensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="isMediaSensitiveToggled" transient="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="language" optional="YES" attributeType="String"/>
<attribute name="likeCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="location" optional="YES" attributeType="Binary"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ final public class TwitterStatus: NSManagedObject {
@NSManaged public private(set) var replyToStatusID: TwitterStatus.ID?
// sourcery: autoUpdatableObject, autoGenerateProperty
@NSManaged public private(set) var replyToUserID: TwitterUser.ID?


// sourcery: autoUpdatableObject, autoGenerateProperty
@NSManaged public private(set) var isMediaSensitive: Bool
// sourcery: autoUpdatableObject
@NSManaged public private(set) var isMediaSensitiveToggled: Bool

// sourcery: autoUpdatableObject, autoGenerateProperty
@NSManaged public private(set) var createdAt: Date
// sourcery: autoUpdatableObject, autoGenerateProperty
Expand Down Expand Up @@ -238,6 +243,7 @@ extension TwitterStatus: AutoGenerateProperty {
public let source: String?
public let replyToStatusID: TwitterStatus.ID?
public let replyToUserID: TwitterUser.ID?
public let isMediaSensitive: Bool
public let createdAt: Date
public let updatedAt: Date

Expand All @@ -252,6 +258,7 @@ extension TwitterStatus: AutoGenerateProperty {
source: String?,
replyToStatusID: TwitterStatus.ID?,
replyToUserID: TwitterUser.ID?,
isMediaSensitive: Bool,
createdAt: Date,
updatedAt: Date
) {
Expand All @@ -265,6 +272,7 @@ extension TwitterStatus: AutoGenerateProperty {
self.source = source
self.replyToStatusID = replyToStatusID
self.replyToUserID = replyToUserID
self.isMediaSensitive = isMediaSensitive
self.createdAt = createdAt
self.updatedAt = updatedAt
}
Expand All @@ -281,6 +289,7 @@ extension TwitterStatus: AutoGenerateProperty {
self.source = property.source
self.replyToStatusID = property.replyToStatusID
self.replyToUserID = property.replyToUserID
self.isMediaSensitive = property.isMediaSensitive
self.createdAt = property.createdAt
self.updatedAt = property.updatedAt
}
Expand All @@ -292,6 +301,7 @@ extension TwitterStatus: AutoGenerateProperty {
update(source: property.source)
update(replyToStatusID: property.replyToStatusID)
update(replyToUserID: property.replyToUserID)
update(isMediaSensitive: property.isMediaSensitive)
update(createdAt: property.createdAt)
update(updatedAt: property.updatedAt)
}
Expand Down Expand Up @@ -377,6 +387,16 @@ extension TwitterStatus: AutoUpdatableObject {
self.replyToUserID = replyToUserID
}
}
public func update(isMediaSensitive: Bool) {
if self.isMediaSensitive != isMediaSensitive {
self.isMediaSensitive = isMediaSensitive
}
}
public func update(isMediaSensitiveToggled: Bool) {
if self.isMediaSensitiveToggled != isMediaSensitiveToggled {
self.isMediaSensitiveToggled = isMediaSensitiveToggled
}
}
public func update(createdAt: Date) {
if self.createdAt != createdAt {
self.createdAt = createdAt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ extension TwitterUser {

public static func predicate(username: String) -> NSPredicate {
return NSPredicate(format: "%K == %@", #keyPath(TwitterUser.username), username)

}

}
Expand Down
13 changes: 13 additions & 0 deletions TwidereSDK/Sources/TwidereCore/Model/User/UserObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ extension UserObject {
}
}

public var authenticationIndex: AuthenticationIndex? {
switch self {
case .twitter(let object):
return object.twitterAuthentication.flatMap {
$0.authenticationIndex
}
case .mastodon(let object):
return object.mastodonAuthentication.flatMap {
$0.authenticationIndex
}
}
}

public var notifications: Set<MastodonNotification> {
switch self {
case .twitter:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ extension TwitterStatus.Property {
},
replyToStatusID: entity.inReplyToStatusIDStr,
replyToUserID: entity.inReplyToUserIDStr,
isMediaSensitive: entity.possiblySensitive ?? false,
createdAt: entity.createdAt,
updatedAt: networkDate
)
Expand Down Expand Up @@ -135,6 +136,7 @@ extension TwitterStatus.Property {
source: status.source,
replyToStatusID: status.repliedToID,
replyToUserID: status.inReplyToUserID,
isMediaSensitive: status.possiblySensitive ?? false,
createdAt: status.createdAt,
updatedAt: networkDate
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public enum TextStyle {
case statusTimestamp
case statusLocation
case statusContent
case statusTranslateButton
case statusMetrics
case userAuthorName
case pollOptionTitle
Expand Down Expand Up @@ -73,6 +74,7 @@ extension TextStyle {
case .statusTimestamp: return 1
case .statusLocation: return 1
case .statusContent: return 0
case .statusTranslateButton: return 1
case .statusMetrics: return 1
case .pollOptionTitle: return 1
case .pollOptionPercentage: return 1
Expand Down Expand Up @@ -116,6 +118,8 @@ extension TextStyle {
return .preferredFont(forTextStyle: .caption1)
case .statusContent:
return .preferredFont(forTextStyle: .body)
case .statusTranslateButton:
return .preferredFont(forTextStyle: .headline)
case .statusMetrics:
return .preferredFont(forTextStyle: .footnote)
case .pollOptionTitle:
Expand Down Expand Up @@ -181,6 +185,8 @@ extension TextStyle {
return .secondaryLabel
case .statusContent:
return .label.withAlphaComponent(0.8)
case .statusTranslateButton:
return .tintColor
case .statusMetrics:
return .secondaryLabel
case .userAuthorName:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ public protocol ListMembershipViewModelDelegate: AnyObject {
}

public final class ListMembershipViewModel {

let logger = Logger(subsystem: "ListMembershipViewModel", category: "ViewModel")

public var id = UUID()
public weak var delegate: ListMembershipViewModelDelegate?

// input
Expand Down Expand Up @@ -55,6 +56,7 @@ public final class ListMembershipViewModel {

extension ListMembershipViewModel {

@MainActor
public func add(
user: UserRecord,
authenticationContext: AuthenticationContext
Expand All @@ -77,6 +79,7 @@ extension ListMembershipViewModel {
}
}

@MainActor
public func remove(
user: UserRecord,
authenticationContext: AuthenticationContext
Expand All @@ -100,3 +103,14 @@ extension ListMembershipViewModel {
}

}

// MARK: - ListMembershipViewModel
extension ListMembershipViewModel: Hashable {
public static func == (lhs: ListMembershipViewModel, rhs: ListMembershipViewModel) -> Bool {
return lhs.id == rhs.id
}

public func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ extension StatusFetchViewModel.Timeline.Home {
public static func fetch(api: APIService, input: Input) async throws -> StatusFetchViewModel.Timeline.Output {
switch input {
case .twitter(let fetchContext):
throw AppError.implicit(.badRequest)

let responses = try await api.twitterHomeTimeline(
query: .init(
sinceID: fetchContext.sinceID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,10 @@ public enum L10n {
/// Search users
public static let searchPlaceholder = L10n.tr("Localizable", "Scene.ComposeUserSearch.SearchPlaceholder", fallback: "Search users")
}
public enum Detail {
/// Detail
public static let title = L10n.tr("Localizable", "Scene.Detail.Title", fallback: "Detail")
}
public enum Drafts {
/// Drafts
public static let title = L10n.tr("Localizable", "Scene.Drafts.Title", fallback: "Drafts")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "اختر %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "ابحث عن وسم";
"Scene.ComposeUserSearch.SearchPlaceholder" = "ابحث عن مستخدم";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "احذف المسودة";
"Scene.Drafts.Actions.EditDraft" = "عدّل المسودة";
"Scene.Drafts.Title" = "المسودات";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "Elecció d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "Cerca etiquetes";
"Scene.ComposeUserSearch.SearchPlaceholder" = "Cerca usuaris";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "Suprimeix l'esborrany";
"Scene.Drafts.Actions.EditDraft" = "Edita l'esborrany";
"Scene.Drafts.Title" = "Esborranys";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "Choice %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "Search hashtag";
"Scene.ComposeUserSearch.SearchPlaceholder" = "Search users";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "Entwurf löschen";
"Scene.Drafts.Actions.EditDraft" = "Entwurf bearbeiten";
"Scene.Drafts.Title" = "Entwürfe";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "Choice %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "Search hashtag";
"Scene.ComposeUserSearch.SearchPlaceholder" = "Search users";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "Delete draft";
"Scene.Drafts.Actions.EditDraft" = "Edit draft";
"Scene.Drafts.Title" = "Drafts";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "Opción %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "Buscar hashtags";
"Scene.ComposeUserSearch.SearchPlaceholder" = "Buscar usuarios";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "Eliminar borrador";
"Scene.Drafts.Actions.EditDraft" = "Editar borrador";
"Scene.Drafts.Title" = "Borradores";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "%d aukera";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "Bilatu traola";
"Scene.ComposeUserSearch.SearchPlaceholder" = "Erabiltzaileak bilatu";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "Ezabatu zirriborroa";
"Scene.Drafts.Actions.EditDraft" = "Editatu zirriborroa";
"Scene.Drafts.Title" = "Zirriborroak";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "Opción %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "Buscar cancelo";
"Scene.ComposeUserSearch.SearchPlaceholder" = "Buscar usuarias";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "Eliminar borrador";
"Scene.Drafts.Actions.EditDraft" = "Editar borrador";
"Scene.Drafts.Title" = "Borradores";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "選択肢 %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "ハッシュタグを検索";
"Scene.ComposeUserSearch.SearchPlaceholder" = "ユーザーを検索";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "下書きを削除";
"Scene.Drafts.Actions.EditDraft" = "下書きを編集";
"Scene.Drafts.Title" = "下書き";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "%d 고르기";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "해시태그 찾기";
"Scene.ComposeUserSearch.SearchPlaceholder" = "사용자 찾기";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "지우기";
"Scene.Drafts.Actions.EditDraft" = "다시 쓰기";
"Scene.Drafts.Title" = "임시 보관함";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "Opção %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "Buscar hashtag";
"Scene.ComposeUserSearch.SearchPlaceholder" = "Buscar usuários";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "Excluir rascunho";
"Scene.Drafts.Actions.EditDraft" = "Editar rascunho";
"Scene.Drafts.Title" = "Rascunhos";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "Seçim %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "Hashtag ara";
"Scene.ComposeUserSearch.SearchPlaceholder" = "Kullanıcıları ara";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "Taslağı sil";
"Scene.Drafts.Actions.EditDraft" = "Taslağı düzenle";
"Scene.Drafts.Title" = "Taslaklar";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
"Scene.Compose.Vote.PlaceholderIndex" = "选项 %d";
"Scene.ComposeHashtagSearch.SearchPlaceholder" = "搜索标签";
"Scene.ComposeUserSearch.SearchPlaceholder" = "搜索用户";
"Scene.Detail.Title" = "Detail";
"Scene.Drafts.Actions.DeleteDraft" = "删除草稿";
"Scene.Drafts.Actions.EditDraft" = "编辑草稿";
"Scene.Drafts.Title" = "草稿";
Expand Down
49 changes: 49 additions & 0 deletions TwidereSDK/Sources/TwidereUI/Container/BadgeClipContainer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// BadgeClipContainer.swift
//
//
// Created by MainasuK on 2023/5/9.
//

import SwiftUI

public struct BadgeClipContainer<Content: View, Badge: View>: View {

public let content: Content
public let badge: Badge

public init(
@ViewBuilder content: () -> Content,
@ViewBuilder badge: () -> Badge
) {
self.content = content()
self.badge = badge()
}

public var body: some View {
ZStack(alignment: Alignment(horizontal: .trailing, vertical: .bottom)) {
content
badge
.scaleEffect(1.2)
.alignmentGuide(HorizontalAlignment.trailing, computeValue: { d in d.width - 4 })
.alignmentGuide(VerticalAlignment.bottom, computeValue: { d in d.height - 4 })
.blendMode(.destinationOut)
.overlay {
badge
}

}
.compositingGroup()
}
}

struct BadgeClipContainer_Previews: PreviewProvider {
static var previews: some View {
BadgeClipContainer(content: {
Color.blue
.frame(width: 44, height: 44)
}, badge: {
Image(uiImage: Asset.Badge.verified.image)
})
}
}

0 comments on commit d5c9371

Please sign in to comment.