Skip to content

Commit f70321f

Browse files
Merge pull request #1 from saumilthecode/server-to-ipad-coms
Server to ipad coms
2 parents abddd01 + c4d7ddc commit f70321f

File tree

5 files changed

+312
-8
lines changed

5 files changed

+312
-8
lines changed

iblot/iblot.xcodeproj/project.pbxproj

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,27 @@
66
objectVersion = 77;
77
objects = {
88

9+
/* Begin PBXContainerItemProxy section */
10+
D24AEA782D995C4100BB1E2E /* PBXContainerItemProxy */ = {
11+
isa = PBXContainerItemProxy;
12+
containerPortal = D2B4D9042D18550F004EA6D5 /* Project object */;
13+
proxyType = 1;
14+
remoteGlobalIDString = D2B4D90B2D18550F004EA6D5;
15+
remoteInfo = iblot;
16+
};
17+
/* End PBXContainerItemProxy section */
18+
919
/* Begin PBXFileReference section */
20+
D24AEA722D995C4100BB1E2E /* iblotUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iblotUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
1021
D2B4D90C2D18550F004EA6D5 /* iblot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iblot.app; sourceTree = BUILT_PRODUCTS_DIR; };
1122
/* End PBXFileReference section */
1223

1324
/* Begin PBXFileSystemSynchronizedRootGroup section */
25+
D24AEA732D995C4100BB1E2E /* iblotUITests */ = {
26+
isa = PBXFileSystemSynchronizedRootGroup;
27+
path = iblotUITests;
28+
sourceTree = "<group>";
29+
};
1430
D2B4D90E2D18550F004EA6D5 /* iblot */ = {
1531
isa = PBXFileSystemSynchronizedRootGroup;
1632
path = iblot;
@@ -19,6 +35,13 @@
1935
/* End PBXFileSystemSynchronizedRootGroup section */
2036

2137
/* Begin PBXFrameworksBuildPhase section */
38+
D24AEA6F2D995C4100BB1E2E /* Frameworks */ = {
39+
isa = PBXFrameworksBuildPhase;
40+
buildActionMask = 2147483647;
41+
files = (
42+
);
43+
runOnlyForDeploymentPostprocessing = 0;
44+
};
2245
D2B4D9092D18550F004EA6D5 /* Frameworks */ = {
2346
isa = PBXFrameworksBuildPhase;
2447
buildActionMask = 2147483647;
@@ -33,6 +56,7 @@
3356
isa = PBXGroup;
3457
children = (
3558
D2B4D90E2D18550F004EA6D5 /* iblot */,
59+
D24AEA732D995C4100BB1E2E /* iblotUITests */,
3660
D2B4D90D2D18550F004EA6D5 /* Products */,
3761
);
3862
sourceTree = "<group>";
@@ -41,13 +65,37 @@
4165
isa = PBXGroup;
4266
children = (
4367
D2B4D90C2D18550F004EA6D5 /* iblot.app */,
68+
D24AEA722D995C4100BB1E2E /* iblotUITests.xctest */,
4469
);
4570
name = Products;
4671
sourceTree = "<group>";
4772
};
4873
/* End PBXGroup section */
4974

5075
/* Begin PBXNativeTarget section */
76+
D24AEA712D995C4100BB1E2E /* iblotUITests */ = {
77+
isa = PBXNativeTarget;
78+
buildConfigurationList = D24AEA7C2D995C4100BB1E2E /* Build configuration list for PBXNativeTarget "iblotUITests" */;
79+
buildPhases = (
80+
D24AEA6E2D995C4100BB1E2E /* Sources */,
81+
D24AEA6F2D995C4100BB1E2E /* Frameworks */,
82+
D24AEA702D995C4100BB1E2E /* Resources */,
83+
);
84+
buildRules = (
85+
);
86+
dependencies = (
87+
D24AEA792D995C4100BB1E2E /* PBXTargetDependency */,
88+
);
89+
fileSystemSynchronizedGroups = (
90+
D24AEA732D995C4100BB1E2E /* iblotUITests */,
91+
);
92+
name = iblotUITests;
93+
packageProductDependencies = (
94+
);
95+
productName = iblotUITests;
96+
productReference = D24AEA722D995C4100BB1E2E /* iblotUITests.xctest */;
97+
productType = "com.apple.product-type.bundle.ui-testing";
98+
};
5199
D2B4D90B2D18550F004EA6D5 /* iblot */ = {
52100
isa = PBXNativeTarget;
53101
buildConfigurationList = D2B4D91B2D185511004EA6D5 /* Build configuration list for PBXNativeTarget "iblot" */;
@@ -80,6 +128,10 @@
80128
LastSwiftUpdateCheck = 1620;
81129
LastUpgradeCheck = 1620;
82130
TargetAttributes = {
131+
D24AEA712D995C4100BB1E2E = {
132+
CreatedOnToolsVersion = 16.2;
133+
TestTargetID = D2B4D90B2D18550F004EA6D5;
134+
};
83135
D2B4D90B2D18550F004EA6D5 = {
84136
CreatedOnToolsVersion = 16.2;
85137
};
@@ -100,11 +152,19 @@
100152
projectRoot = "";
101153
targets = (
102154
D2B4D90B2D18550F004EA6D5 /* iblot */,
155+
D24AEA712D995C4100BB1E2E /* iblotUITests */,
103156
);
104157
};
105158
/* End PBXProject section */
106159

107160
/* Begin PBXResourcesBuildPhase section */
161+
D24AEA702D995C4100BB1E2E /* Resources */ = {
162+
isa = PBXResourcesBuildPhase;
163+
buildActionMask = 2147483647;
164+
files = (
165+
);
166+
runOnlyForDeploymentPostprocessing = 0;
167+
};
108168
D2B4D90A2D18550F004EA6D5 /* Resources */ = {
109169
isa = PBXResourcesBuildPhase;
110170
buildActionMask = 2147483647;
@@ -115,6 +175,13 @@
115175
/* End PBXResourcesBuildPhase section */
116176

117177
/* Begin PBXSourcesBuildPhase section */
178+
D24AEA6E2D995C4100BB1E2E /* Sources */ = {
179+
isa = PBXSourcesBuildPhase;
180+
buildActionMask = 2147483647;
181+
files = (
182+
);
183+
runOnlyForDeploymentPostprocessing = 0;
184+
};
118185
D2B4D9082D18550F004EA6D5 /* Sources */ = {
119186
isa = PBXSourcesBuildPhase;
120187
buildActionMask = 2147483647;
@@ -124,7 +191,54 @@
124191
};
125192
/* End PBXSourcesBuildPhase section */
126193

194+
/* Begin PBXTargetDependency section */
195+
D24AEA792D995C4100BB1E2E /* PBXTargetDependency */ = {
196+
isa = PBXTargetDependency;
197+
target = D2B4D90B2D18550F004EA6D5 /* iblot */;
198+
targetProxy = D24AEA782D995C4100BB1E2E /* PBXContainerItemProxy */;
199+
};
200+
/* End PBXTargetDependency section */
201+
127202
/* Begin XCBuildConfiguration section */
203+
D24AEA7A2D995C4100BB1E2E /* Debug */ = {
204+
isa = XCBuildConfiguration;
205+
buildSettings = {
206+
CODE_SIGN_STYLE = Automatic;
207+
CURRENT_PROJECT_VERSION = 1;
208+
DEVELOPMENT_TEAM = U4679NLU6P;
209+
GENERATE_INFOPLIST_FILE = YES;
210+
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
211+
MARKETING_VERSION = 1.0;
212+
PRODUCT_BUNDLE_IDENTIFIER = club.bbsshack.iblotUITests;
213+
PRODUCT_NAME = "$(TARGET_NAME)";
214+
SDKROOT = iphoneos;
215+
SWIFT_EMIT_LOC_STRINGS = NO;
216+
SWIFT_VERSION = 5.0;
217+
TARGETED_DEVICE_FAMILY = "1,2";
218+
TEST_TARGET_NAME = iblot;
219+
};
220+
name = Debug;
221+
};
222+
D24AEA7B2D995C4100BB1E2E /* Release */ = {
223+
isa = XCBuildConfiguration;
224+
buildSettings = {
225+
CODE_SIGN_STYLE = Automatic;
226+
CURRENT_PROJECT_VERSION = 1;
227+
DEVELOPMENT_TEAM = U4679NLU6P;
228+
GENERATE_INFOPLIST_FILE = YES;
229+
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
230+
MARKETING_VERSION = 1.0;
231+
PRODUCT_BUNDLE_IDENTIFIER = club.bbsshack.iblotUITests;
232+
PRODUCT_NAME = "$(TARGET_NAME)";
233+
SDKROOT = iphoneos;
234+
SWIFT_EMIT_LOC_STRINGS = NO;
235+
SWIFT_VERSION = 5.0;
236+
TARGETED_DEVICE_FAMILY = "1,2";
237+
TEST_TARGET_NAME = iblot;
238+
VALIDATE_PRODUCT = YES;
239+
};
240+
name = Release;
241+
};
128242
D2B4D9192D185511004EA6D5 /* Debug */ = {
129243
isa = XCBuildConfiguration;
130244
buildSettings = {
@@ -258,10 +372,11 @@
258372
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
259373
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
260374
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
375+
INFOPLIST_KEY_UIRequiresFullScreen = YES;
376+
INFOPLIST_KEY_UIStatusBarHidden = YES;
261377
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
262378
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
263-
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
264-
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
379+
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
265380
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
266381
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
267382
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
@@ -297,10 +412,11 @@
297412
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
298413
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
299414
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
415+
INFOPLIST_KEY_UIRequiresFullScreen = YES;
416+
INFOPLIST_KEY_UIStatusBarHidden = YES;
300417
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
301418
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
302-
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
303-
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
419+
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
304420
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
305421
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
306422
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
@@ -320,6 +436,15 @@
320436
/* End XCBuildConfiguration section */
321437

322438
/* Begin XCConfigurationList section */
439+
D24AEA7C2D995C4100BB1E2E /* Build configuration list for PBXNativeTarget "iblotUITests" */ = {
440+
isa = XCConfigurationList;
441+
buildConfigurations = (
442+
D24AEA7A2D995C4100BB1E2E /* Debug */,
443+
D24AEA7B2D995C4100BB1E2E /* Release */,
444+
);
445+
defaultConfigurationIsVisible = 0;
446+
defaultConfigurationName = Release;
447+
};
323448
D2B4D9072D18550F004EA6D5 /* Build configuration list for PBXProject "iblot" */ = {
324449
isa = XCConfigurationList;
325450
buildConfigurations = (

iblot/iblot/ContentView.swift

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,69 @@ struct ContentView: View {
1212
@State private var currentLine: [CGPoint] = []
1313
@State private var canvasSize: CGSize = CGSize(width: 250, height: 250)
1414
@State private var isErasing: Bool = false
15+
@State private var showingUploadConfirmation = false
16+
@State private var showingUploadSuccess = false
17+
@State private var showingShareSheet = false
18+
@State private var showingClearConfirmation = false
1519

20+
// Add function to render and upload image
21+
func renderAndUploadImage(size: CGSize) {
22+
let renderer = ImageRenderer(content:
23+
Canvas { context, _ in
24+
for line in lines {
25+
drawLine(context: context, line: line, size: size)
26+
}
27+
}
28+
.frame(width: size.width, height: size.height)
29+
)
30+
31+
// Configure renderer for transparency
32+
renderer.isOpaque = false
33+
34+
guard let uiImage = renderer.uiImage else { return }
35+
guard let pngData = uiImage.pngData() else { return }
36+
37+
let url = URL(string: "https://dino.bbsshack.club/upload")!
38+
var request = URLRequest(url: url)
39+
request.httpMethod = "POST"
40+
41+
let boundary = "Boundary-\(UUID().uuidString)"
42+
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
43+
44+
var body = Data()
45+
// Generate unique filename using timestamp and random string
46+
let timestamp = Int(Date().timeIntervalSince1970)
47+
let randomString = UUID().uuidString.prefix(8)
48+
let filename = "drawing_\(timestamp)_\(randomString).png"
49+
let fieldName = "file"
50+
51+
body.append("--\(boundary)\r\n".data(using: .utf8)!)
52+
body.append("Content-Disposition: form-data; name=\"\(fieldName)\"; filename=\"\(filename)\"\r\n".data(using: .utf8)!)
53+
body.append("Content-Type: image/png\r\n\r\n".data(using: .utf8)!)
54+
body.append(pngData)
55+
body.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
56+
57+
request.httpBody = body
58+
59+
URLSession.shared.dataTask(with: request) { data, response, error in
60+
if let error = error {
61+
print("Upload error: \(error)")
62+
return
63+
}
64+
if let httpResponse = response as? HTTPURLResponse {
65+
print("Upload status: \(httpResponse.statusCode)")
66+
if httpResponse.statusCode == 200 {
67+
DispatchQueue.main.async {
68+
showingUploadSuccess = true
69+
}
70+
}
71+
}
72+
}.resume()
73+
}
74+
75+
1676
var body: some View {
17-
VStack {
77+
VStack(spacing: 20) {
1878
GeometryReader { geometry in
1979
Canvas { context, size in
2080
DispatchQueue.main.async {
@@ -55,22 +115,58 @@ struct ContentView: View {
55115
.border(Color.black, width: 1)
56116
}
57117

118+
// Drawing controls directly below canvas
58119
HStack {
59120
Button("Clear") {
60-
lines.removeAll()
121+
showingClearConfirmation = true
61122
}
62123
.padding()
124+
.foregroundColor(.red)
125+
.alert("Confirm Clear", isPresented: $showingClearConfirmation) {
126+
Button("Cancel", role: .cancel) { }
127+
Button("Clear", role: .destructive) {
128+
lines.removeAll()
129+
}
130+
} message: {
131+
Text("Are you sure you want to clear the drawing?")
132+
}
63133

64134
Button(isErasing ? "Draw" : "Erase") {
65135
isErasing.toggle()
66136
}
67137
.padding()
68138
.foregroundColor(isErasing ? .red : .blue)
139+
}
140+
141+
Spacer()
142+
143+
// Upload and Airdrop buttons at bottom
144+
HStack {
145+
Button("Upload") {
146+
showingUploadConfirmation = true
147+
}
148+
.padding()
149+
.alert("Confirm Upload", isPresented: $showingUploadConfirmation) {
150+
Button("Cancel", role: .cancel) { }
151+
Button("Upload") {
152+
renderAndUploadImage(size: canvasSize)
153+
}
154+
} message: {
155+
Text("Are you sure you want to upload this drawing?")
156+
}
157+
.alert("Success", isPresented: $showingUploadSuccess) {
158+
Button("OK", role: .cancel) { }
159+
} message: {
160+
Text("Your drawing was successfully uploaded!")
161+
}
69162

70-
ShareLink(item: generateJavaScriptCode(from: lines, canvasSize: canvasSize)) {
71-
Text("AIRDROP RAAAH")
163+
Button("Airdrop!") {
164+
showingShareSheet = true
72165
}
73166
.padding()
167+
.sheet(isPresented: $showingShareSheet) {
168+
ShareSheet(activityItems: [generateJavaScriptCode(from: lines, canvasSize: canvasSize)])
169+
}
74170
}
75171
}
76172
.padding()
@@ -120,6 +216,17 @@ struct ContentView: View {
120216
}
121217
}
122218

219+
struct ShareSheet: UIViewControllerRepresentable {
220+
let activityItems: [Any]
221+
222+
func makeUIViewController(context: Context) -> UIActivityViewController {
223+
let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
224+
return controller
225+
}
226+
227+
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
228+
}
229+
123230
struct ContentView_Previews: PreviewProvider {
124231
static var previews: some View {
125232
ContentView()

0 commit comments

Comments
 (0)