Skip to content

Commit

Permalink
Initial Permission Support (SwiftcordApp#164)
Browse files Browse the repository at this point in the history
* feat(permissions): channel visibility based on permissions

* fix: remove list dividers added in Xcode 15

* fix(onboarding): move attributed title declaration out of view body
  • Loading branch information
cryptoAlgorithm committed Sep 11, 2023
1 parent 966b03a commit 2fac042
Show file tree
Hide file tree
Showing 13 changed files with 229 additions and 59 deletions.
6 changes: 6 additions & 0 deletions Swiftcord.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@
DA7721FD2896BD4D0007BE26 /* URL+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7721FC2896BD4D0007BE26 /* URL+.swift */; };
DA7721FE2896BD4D0007BE26 /* URL+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7721FC2896BD4D0007BE26 /* URL+.swift */; };
DA8AEA6829029747007BAAEA /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = DA8AEA6729029747007BAAEA /* Introspect */; };
DA9029572A0CC450008E05FA /* Permissions+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9029562A0CC450008E05FA /* Permissions+.swift */; };
DA9029582A0CC454008E05FA /* Permissions+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9029562A0CC450008E05FA /* Permissions+.swift */; };
DA91016C28BF8F1F00DD076B /* CreditsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB1E46928A0A59500645FCD /* CreditsView.swift */; };
DA91017028C38E0400DD076B /* CurrentUserFooter+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA91016F28C38E0400DD076B /* CurrentUserFooter+.swift */; };
DA91017128C38E0400DD076B /* CurrentUserFooter+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA91016F28C38E0400DD076B /* CurrentUserFooter+.swift */; };
Expand Down Expand Up @@ -352,6 +354,7 @@
DA6E89EF2876BC7E00BB05E7 /* AppSettingsAdvancedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettingsAdvancedView.swift; sourceTree = "<group>"; };
DA7720CF283F184100D3C335 /* NavigationCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationCommands.swift; sourceTree = "<group>"; };
DA7721FC2896BD4D0007BE26 /* URL+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+.swift"; sourceTree = "<group>"; };
DA9029562A0CC450008E05FA /* Permissions+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Permissions+.swift"; sourceTree = "<group>"; };
DA91016F28C38E0400DD076B /* CurrentUserFooter+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CurrentUserFooter+.swift"; sourceTree = "<group>"; };
DA91017228C38EA300DD076B /* AccountRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountRow.swift; sourceTree = "<group>"; };
DA91017528C3989E00DD076B /* AccountMeta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountMeta.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -831,6 +834,7 @@
DA32EF5127C8FBB200A9ED72 /* User+.swift */,
DA54D5752844B9C500B11857 /* CurrentUser+.swift */,
DAC437782900F3FD00D3A894 /* Snowflake+.swift */,
DA9029562A0CC450008E05FA /* Permissions+.swift */,
);
path = DiscordAPI;
sourceTree = "<group>";
Expand Down Expand Up @@ -1184,6 +1188,7 @@
36429989286801C900483D0A /* UserSettingsProfileView.swift in Sources */,
DA91017A28C4726300DD076B /* AccountSwitcher.swift in Sources */,
3642998A286801C900483D0A /* ServerView.swift in Sources */,
DA9029582A0CC454008E05FA /* Permissions+.swift in Sources */,
3642998B286801C900483D0A /* SwiftcordApp.swift in Sources */,
368B6730287A20F800E37B33 /* ServerJoinView.swift in Sources */,
);
Expand Down Expand Up @@ -1270,6 +1275,7 @@
DAB1E46C28A10BB100645FCD /* BetterImageView.swift in Sources */,
DAA57E242892270800C9A931 /* SwiftyGifNSView.swift in Sources */,
9FCE7B1D28C7140100213A3F /* ServerFolder.swift in Sources */,
DA9029572A0CC450008E05FA /* Permissions+.swift in Sources */,
DA2BD30C284CB38B00EBB8D6 /* AppSettingsAppearanceView.swift in Sources */,
DAAFB5C3282AA5C700807B54 /* MessageInfoBarView.swift in Sources */,
DA32EF5027C8D7E000A9ED72 /* Message+.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@
"revision" : "2214f9ee2476f28af64cb38359defe59e85197a1"
}
},
{
"identity" : "bitbytedata",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tsolomko/BitByteData",
"state" : {
"revision" : "36df26fe4586b4f23d76cfd8b47076998343a2b2",
"version" : "2.0.3"
}
},
{
"identity" : "discordkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SwiftcordApp/DiscordKit",
"state" : {
"branch" : "main",
"revision" : "dc16b007a5dbfdf008c51897257af36713e91c19"
"revision" : "1474f71dabb18050cc2422d08643731b7aecf6a4"
}
},
{
Expand All @@ -27,6 +36,15 @@
"version" : "4.1.3"
}
},
{
"identity" : "opencombine",
"kind" : "remoteSourceControl",
"location" : "https://github.com/OpenCombine/OpenCombine.git",
"state" : {
"revision" : "8576f0d579b27020beccbccc3ea6844f3ddfc2c2",
"version" : "0.14.0"
}
},
{
"identity" : "plcrashreporter",
"kind" : "remoteSourceControl",
Expand Down Expand Up @@ -63,6 +81,15 @@
"version" : "2.3.2"
}
},
{
"identity" : "swcompression",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tsolomko/SWCompression.git",
"state" : {
"revision" : "cd39ca0a3b269173bab06f68b182b72fa690765c",
"version" : "4.8.5"
}
},
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
Expand All @@ -72,13 +99,31 @@
"version" : "1.5.2"
}
},
{
"identity" : "swift-nio",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio.git",
"state" : {
"revision" : "124119f0bb12384cef35aa041d7c3a686108722d",
"version" : "2.40.0"
}
},
{
"identity" : "swift-nio-ssl",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-ssl.git",
"state" : {
"revision" : "1750873bce84b4129b5303655cce2c3d35b9ed3a",
"version" : "2.19.0"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "0af9125c4eae12a4973fb66574c53a54962a9e1e",
"version" : "1.21.0"
"revision" : "f25867a208f459d3c5a06935dceb9083b11cd539",
"version" : "1.22.0"
}
},
{
Expand Down Expand Up @@ -107,6 +152,15 @@
"branch" : "fix-timer-crash",
"revision" : "32a6bd02c9c44c8cdd4e98f46037678ee1abecbb"
}
},
{
"identity" : "websocket.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tesseract-one/WebSocket.swift.git",
"state" : {
"revision" : "9f616c35127c83651d3112f8bdb41284d3c5c213",
"version" : "0.2.0"
}
}
],
"version" : 2
Expand Down
10 changes: 10 additions & 0 deletions Swiftcord/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ private extension AppDelegate {
private extension AppDelegate {
/// Overwrite shared URLCache with a higher capacity one
func setupURLCache() {
/*let cachePath = (try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true))?.appendingPathComponent("sharedCache", isDirectory: false)
if let cachePath {
do {
try FileManager.default.createDirectory(at: cachePath, withIntermediateDirectories: true)
} catch {
print("Create new cache dir fail! \(error)")
return
}
}
print("Cache path: \(cachePath)")*/
URLCache.shared = URLCache(
memoryCapacity: 32 * 1024 * 1024, // 32MB
diskCapacity: 256 * 1024 * 1024, // 256MB
Expand Down
18 changes: 18 additions & 0 deletions Swiftcord/Utils/Extensions/DiscordAPI/Permissions+.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Permissions+.swift
// Swiftcord
//
// Created by Vincent Kwok on 11/5/23.
//

import Foundation
import DiscordKitCore

public extension Permissions {
static let all: Permissions = .init(rawValue: 0x7FFFFFFFFFFF)

mutating func applyOverwrite(_ overwrite: PermOverwrite) {
remove(overwrite.deny)
formUnion(overwrite.allow)
}
}
12 changes: 6 additions & 6 deletions Swiftcord/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ struct ContentView: View {
folder.guild_ids.contains(guild.id)
}
}
.sorted { lhs, rhs in lhs.joined_at! > rhs.joined_at! }
.sorted { lhs, rhs in lhs.joined_at > rhs.joined_at }
.map { ServerListItem.guild($0) }
return unsortedGuilds + gateway.guildFolders.compactMap { folder -> ServerListItem? in
if folder.id != nil {
let guilds = folder.guild_ids.compactMap {
gateway.cache.guilds[$0]
}
let name = folder.name ?? String(guilds.map { $0.name }.joined(separator: ", "))
let name = folder.name ?? String(guilds.map { $0.properties.name }.joined(separator: ", "))
return .guildFolder(ServerFolder.GuildFolder(
name: name, guilds: guilds, color: folder.color.flatMap { Color(hex: $0) } ?? Color.accentColor
))
Expand Down Expand Up @@ -105,8 +105,8 @@ struct ContentView: View {
case .guild(let guild):
ServerButton(
selected: state.selectedGuildID == guild.id || loadingGuildID == guild.id,
name: guild.name,
serverIconURL: guild.icon != nil ? "\(DiscordKitConfig.default.cdnURL)icons/\(guild.id)/\(guild.icon!).webp?size=240" : nil,
name: guild.properties.name,
serverIconURL: guild.properties.icon != nil ? "\(DiscordKitConfig.default.cdnURL)icons/\(guild.id)/\(guild.properties.icon!).webp?size=240" : nil,
isLoading: loadingGuildID == guild.id,
onSelect: { state.selectedGuildID = guild.id }
)
Expand Down Expand Up @@ -142,7 +142,7 @@ struct ContentView: View {
ServerView(
guild: state.selectedGuildID == nil
? nil
: (state.selectedGuildID == "@me" ? makeDMGuild() : gateway.cache.guilds[state.selectedGuildID!]), serverCtx: state.serverCtx
: ( gateway.cache.guilds[state.selectedGuildID!]), serverCtx: state.serverCtx
)
}
// Blur the area behind the toolbar so the content doesn't show thru
Expand Down Expand Up @@ -217,7 +217,7 @@ struct ContentView: View {
}

private enum ServerListItem: Identifiable {
case guild(Guild), guildFolder(ServerFolder.GuildFolder)
case guild(PreloadedGuild), guildFolder(ServerFolder.GuildFolder)

var id: String {
switch self {
Expand Down
2 changes: 1 addition & 1 deletion Swiftcord/Views/Message/Attachment/AttachmentAudio.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct AttachmentAudio: View {
audioManager.append(
source: url,
filename: attachment.filename,
from: "\(serverCtx.guild!.name) > #\(serverCtx.channel?.name ?? "")"
from: "\(serverCtx.guild!.properties.name) > #\(serverCtx.channel?.name ?? "")"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct DefaultMessageView: View {
.italic()
.foregroundColor(Color(NSColor.textColor).opacity(0.4))
}
.lineSpacing(3)
.lineSpacing(4)
.textSelection(.enabled)
}
if let stickerItems = message.sticker_items {
Expand Down
20 changes: 16 additions & 4 deletions Swiftcord/Views/Message/MessagesView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ extension View {
}
}

extension View {
@ViewBuilder public func removeSeparator() -> some View {
if #available(macOS 13.0, *) {
self.listRowSeparator(.hidden).listSectionSeparator(.hidden)
} else {
self
}
}
}

struct NewAttachmentError: Identifiable {
var id: String { title + message }
let title: String
Expand Down Expand Up @@ -188,23 +198,25 @@ struct MessagesView: View {
DayDividerView(date: msg.timestamp)
}
}
.flip()
.zeroRowInsets()
.fixedSize(horizontal: false, vertical: true)
}

@ViewBuilder
private var historyList: some View {
ScrollViewReader { proxy in
List {
Spacer(minLength: max(messageInputHeight-44-7, 0) + (viewModel.showingInfoBar ? 24 : 0)).zeroRowInsets()

history
history.flip().removeSeparator()

if viewModel.reachedTop {
MessagesViewHeader(chl: ctx.channel).zeroRowInsets().flip()
MessagesViewHeader(chl: ctx.channel).zeroRowInsets().removeSeparator().flip()
} else {
loadingSkeleton
.zeroRowInsets()
.flip()
.removeSeparator()
.onAppear { if viewModel.fetchMessagesTask == nil { fetchMoreMessages() } }
.onDisappear {
if let loadTask = viewModel.fetchMessagesTask {
Expand Down Expand Up @@ -260,7 +272,7 @@ struct MessagesView: View {
let typingMembers = ctx.channel == nil
? []
: ctx.typingStarted[ctx.channel!.id]?
.map { $0.member?.nick ?? $0.member?.user!.username ?? "" } ?? []
.map { $0.member?.nick ?? $0.member?.user?.username ?? "" } ?? []

if !typingMembers.isEmpty {
HStack {
Expand Down
24 changes: 12 additions & 12 deletions Swiftcord/Views/OnboardingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ struct OnboardingWelcomeView: View {
let loadingNew: Bool
let hasNew: Bool

var body: some View {
VStack(alignment: .leading, spacing: 16) {
Group {
var attributedTitle: AttributedString {
var attributedString: AttributedString = .init(localized: "onboarding.title \(appName ?? "")")
var attributedTitle: AttributedString {
var attributedString: AttributedString = .init(localized: "onboarding.title \(appName ?? "")")

let appNameRange = attributedString.range(of: appName ?? "")
let appNameRange = attributedString.range(of: appName ?? "")

if let appNameRange = appNameRange {
attributedString[appNameRange].foregroundColor = .accentColor
attributedString[appNameRange].font = .system(size: 72).weight(.heavy)
}
if let appNameRange = appNameRange {
attributedString[appNameRange].foregroundColor = .accentColor
attributedString[appNameRange].font = .system(size: 72).weight(.heavy)
}

return attributedString
}
return attributedString
}

var body: some View {
VStack(alignment: .leading, spacing: 16) {
Group {
Text(attributedTitle)
.font(.largeTitle)

Expand Down
2 changes: 1 addition & 1 deletion Swiftcord/Views/Server/ChannelButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct GuildChButton: View {

var body: some View {
Button { selectedCh = channel } label: {
let image = (serverCtx.guild?.rules_channel_id != nil && serverCtx.guild?.rules_channel_id! == channel.id) ? "newspaper.fill" : (chIcons[channel.type] ?? "number")
let image = serverCtx.guild?.properties.rules_channel_id == channel.id ? "newspaper.fill" : (chIcons[channel.type] ?? "number")
Label(channel.label() ?? "nil", systemImage: image)
.padding(.vertical, 5)
.padding(.horizontal, 4)
Expand Down
Loading

0 comments on commit 2fac042

Please sign in to comment.