Skip to content

Commit

Permalink
Feat: added support for faving posts, added API key auth, UI code cle…
Browse files Browse the repository at this point in the history
…anup
  • Loading branch information
CaramelKat committed Dec 19, 2024
1 parent aa9e340 commit cb4b56a
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 170 deletions.
Binary file modified .DS_Store
Binary file not shown.
16 changes: 8 additions & 8 deletions Tanuki's Stash.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
027E2B4527850E2E00FCEDB2 /* VideoPlayer in Frameworks */ = {isa = PBXBuildFile; productRef = 027E2B4427850E2E00FCEDB2 /* VideoPlayer */; };
027E2B492789487000FCEDB2 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 027E2B482789486F00FCEDB2 /* SettingsView.swift */; };
02D21B1E288279C800239990 /* TagModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D21B1D288279C800239990 /* TagModel.swift */; };
02D21B2028827AA700239990 /* TagManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D21B1F28827AA700239990 /* TagManager.swift */; };
02D21B2028827AA700239990 /* ApiManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D21B1F28827AA700239990 /* ApiManager.swift */; };
50914FA92C26652000E52BD0 /* AttributedText in Frameworks */ = {isa = PBXBuildFile; productRef = 50914FA82C26652000E52BD0 /* AttributedText */; };
50C1182B2B648B18003F5D4E /* AlertToast in Frameworks */ = {isa = PBXBuildFile; productRef = 50C1182A2B648B18003F5D4E /* AlertToast */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -58,7 +58,7 @@
027E2B332784DFA200FCEDB2 /* libswift_Concurrency.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswift_Concurrency.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/usr/lib/swift/libswift_Concurrency.tbd; sourceTree = DEVELOPER_DIR; };
027E2B482789486F00FCEDB2 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
02D21B1D288279C800239990 /* TagModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagModel.swift; sourceTree = "<group>"; };
02D21B1F28827AA700239990 /* TagManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagManager.swift; sourceTree = "<group>"; };
02D21B1F28827AA700239990 /* ApiManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiManager.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -125,7 +125,7 @@
027E2B482789486F00FCEDB2 /* SettingsView.swift */,
026C76DD27D6CC3D00BBE65A /* SearchView.swift */,
02D21B1D288279C800239990 /* TagModel.swift */,
02D21B1F28827AA700239990 /* TagManager.swift */,
02D21B1F28827AA700239990 /* ApiManager.swift */,
);
path = "Tanuki's Stash";
sourceTree = "<group>";
Expand Down Expand Up @@ -293,7 +293,7 @@
files = (
0202880D2783C74500341901 /* ContentView.swift in Sources */,
02D21B1E288279C800239990 /* TagModel.swift in Sources */,
02D21B2028827AA700239990 /* TagManager.swift in Sources */,
02D21B2028827AA700239990 /* ApiManager.swift in Sources */,
020288352783E96600341901 /* PostModel.swift in Sources */,
027E2B492789487000FCEDB2 /* SettingsView.swift in Sources */,
027E2B302784CF9700FCEDB2 /* PostView.swift in Sources */,
Expand Down Expand Up @@ -456,7 +456,7 @@
CODE_SIGN_ENTITLEMENTS = "Tanuki's Stash/Tanuki's Stash.entitlements";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_ASSET_PATHS = "\"Tanuki's Stash/Preview Content\"";
DEVELOPMENT_TEAM = 8Y8A9FZ38R;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
Expand All @@ -475,7 +475,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.0.3;
MARKETING_VERSION = 0.0.5;
PRODUCT_BUNDLE_IDENTIFIER = dev.jemsoftware.tanukistash;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
Expand All @@ -494,7 +494,7 @@
CODE_SIGN_ENTITLEMENTS = "Tanuki's Stash/Tanuki's Stash.entitlements";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_ASSET_PATHS = "\"Tanuki's Stash/Preview Content\"";
DEVELOPMENT_TEAM = 8Y8A9FZ38R;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
Expand All @@ -513,7 +513,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.0.3;
MARKETING_VERSION = 0.0.5;
PRODUCT_BUNDLE_IDENTIFIER = dev.jemsoftware.tanukistash;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
Expand Down
121 changes: 121 additions & 0 deletions Tanuki's Stash/ApiManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// TagManager.swift
// Tanuki's Stash
//
// Created by Jemma Poffinbarger on 7/15/22.
//

import Foundation
import SwiftUI

var source = defaults.string(forKey: "api_source") ?? "e926.net";
var API_KEY = defaults.string(forKey: "API_KEY") ?? "";
var username = defaults.string(forKey: "username") ?? "";
var tagList = [String]();
let userAgent: String = "Tanukis%20Stash/0.0.5%20(by%20JemTanuki%20on%20e621)";
let AUTH_STRING: String = "\(username):\(API_KEY)".data(using: .utf8)?.base64EncodedString() ?? "";

func fetchTags(_ text: String) async {
do {
let url = URL(string: "https://\(source)/tags/autocomplete.json?search%5Bname_matches%5D=\(text)&expiry=7&_client=\(userAgent)")!
let (data, _) = try await URLSession.shared.data(from: url)
let parsedData = try JSONDecoder().decode([TagContent].self, from: data)
let tags = parsedData;
await processTags(tags);
} catch {
print(error);
}
}

func processTags(_ tags: [TagContent]) async {
for tag in tags {
tagList.append(tag.name);
}
}

func parseSearch(_ searchText: String) -> String {
if(searchText.contains(" ")) {
let index = searchText.lastIndex(of: " ");
if(index != nil) {
return String(searchText[index!...]).trimmingCharacters(in: .whitespacesAndNewlines);
}
else {return "";}
}
else { return searchText; }
}

func createTagList(_ search: String) async -> [String] {
tagList.removeAll();
let newSearchText = parseSearch(search);
if(newSearchText.count >= 3) {
await fetchTags(newSearchText);
}
return tagList;
}

func fetchRecentPosts(_ page: Int, _ limit: Int, _ tags: String) async -> [PostContent] {
do {
let encoded = tags.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
let url = "https://\(source)/posts.json?tags=\(encoded ?? "")&limit=\(limit)&page=\(page)"
let data = await makeRequest(url: url, method: "GET", body: nil);
if (data) == nil { return []; }
let parsedData = try JSONDecoder().decode(Posts.self, from: data!)
return parsedData.posts;
} catch {
print(error);
return [];
}
}

func fetchMoreRecentPosts(_ page: Int, _ limit: Int, _ tags: String) async -> [PostContent] {
do {
let encoded = tags.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
let url = "https://\(source)/posts.json?tags=\(encoded ?? "")&limit=\(limit)&page=\(page)"
let data = await makeRequest(url: url, method: "GET", body: nil);
if (data) == nil { return []; }
let parsedData = try JSONDecoder().decode(Posts.self, from: data!)
return parsedData.posts;
} catch {
print(error);
return [];
}
}

func favoritePost(postId: Int) async -> Bool {
let url = "https://\(source)/favorites.json?post_id=\(postId)"
let data = await makeRequest(url: url, method: "POST", body: nil);
if (data) == nil { return false; }
return true;
}

func unFavoritePost(postId: Int) async -> Bool {
let url = "https://\(source)/favorites/\(postId).json"
let data = await makeRequest(url: url, method: "DELETE", body: nil);
if (data) == nil { return true; }
return false;
}

func makeRequest(url: String, method: String, body: Data?) async -> Data? {
let url = URL(string: url)
var request = URLRequest(url: url!)
request.httpMethod = method
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue(userAgent, forHTTPHeaderField: "User-Agent")
request.addValue("Basic \(AUTH_STRING)", forHTTPHeaderField: "Authorization")
print("Making request to \(url!)")
print("Method: \(method)")
print("Body: \(body?.debugDescription ?? "")")
do {
if !(body?.isEmpty ?? false) {
request.httpBody = body
}
let (data, _) = try await URLSession.shared.data(for: request);
return data;

} catch {
DispatchQueue.main.async {
print("Failed to make request")
}
return nil
}
}
2 changes: 1 addition & 1 deletion Tanuki's Stash/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ContentView.swift
// Tanuki's Stash
//
// Created by Jay Poffinbarger on 1/3/22.
// Created by Jemma Poffinbarger on 1/3/22.
//

import SwiftUI
Expand Down
2 changes: 1 addition & 1 deletion Tanuki's Stash/PostModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct PostContent: Decodable {
let uploader_id: Int;
let description: String;
let comment_count: Int;
let is_favorited: Bool;
var is_favorited: Bool;
let has_notes: Bool;
let duration: Float?;
}
Expand Down
24 changes: 18 additions & 6 deletions Tanuki's Stash/PostView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,20 @@ struct PostView: View {
.padding(10.0)
.background(Color.gray)
.cornerRadius(10)


if post.is_favorited {
Button("Un-Favorite") {
Task.init {
post.is_favorited = await unFavoritePost(postId: post.id);
}
}
}
else {
Button("Favorite") {
Task.init {
post.is_favorited = await favoritePost(postId: post.id);
}
}
}
VStack(alignment: .leading) {
AttributedText(descParser(text: .init(post.description)))
.frame(maxWidth: .infinity, alignment: .leading)
Expand Down Expand Up @@ -117,10 +129,10 @@ struct PostView: View {
}
func fetchRecentPosts(postID: Int) async {
do {
let userAgent = "Tanukis%20Stash/1.0%20(by%20JayDaBirb%20on%20e621)"
let url = URL(string: "https://\(source)/posts/\(postID).json?_client=\(userAgent)")!
let (data, _) = try await URLSession.shared.data(from: url)
let parsedData = try JSONDecoder().decode(Post.self, from: data)
let url = "https://\(source)/posts/\(postID).json?_client=\(userAgent)"
let data = await makeRequest(url: url, method: "GET", body: nil);
if (data) == nil { return; }
let parsedData = try JSONDecoder().decode(Post.self, from: data!)
parentPost = parsedData.post;
} catch {
print(error);
Expand Down
Loading

0 comments on commit cb4b56a

Please sign in to comment.