Commit 4ee212f0 authored by Wei Han's avatar Wei Han

ui fixes

parent abca9aa8
......@@ -12,10 +12,10 @@ import { QmsDashboardView } from 'QmsPlugin';
function App() {
const isDarkMode = useColorScheme() === 'dark';
const clientID = '3';
const clientCode = 'kita';
const clientID = '1';
const clientCode = 'spt';
const userToken =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImF0aGlyYWh6YWlkaUBjb252ZXAuY29tIiwicGFzc3dvcmQiOiIkMnkkMTAkNU9xYklqMnZ6UHJwckJrcVd5c3I2LmJCc1hVYS9Hd014eUhnL3RhUUhPUkNQcGdmTG8yakciLCJzdWIiOjIxNzAsImlzcyI6Imh0dHBzOi8va2l0YWRldi5jb21tdWRlc2suY29tL2FwaS9vd25lci9hdXRoL3Bhc3N3b3JkbGVzc19sb2dpbiIsImlhdCI6MTc2MDMxNTM1MiwiZXhwIjoyMDc1ODg0ODcyLCJuYmYiOjE3NjAzMTUzNTIsImp0aSI6IktoQmNyQnJEdDVNdDZlWmMifQ.JnxGbZ7hTeoOr6oibIzZMphgyKtTo2Aq9Efx6mrGfFA';
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzY29wZSI6InNlcnZlci10by1zZXJ2ZXIiLCJmcmFtZXdvcmstYXBpIjp0cnVlLCJjb21wYW55X2NvZGUiOiJTUFQiLCJzdWIiOjE1NTcsImlzcyI6Imh0dHBzOi8vc3B0ZXN0LmNvbW11ZGVzay5jb20vYXBpL2ZyYW1ld29yay9vd25lci9hdXRoL2NsaWVudF9hdXRoZW50aWNhdGlvbiIsImlhdCI6MTc2Nzc1MjU5OSwiZXhwIjoyMDgzMzIyMTE5LCJuYmYiOjE3Njc3NTI1OTksImp0aSI6IktEcmhmSXgzeWU0WmxaUEYifQ.Bv4ZSjGRm9YYOjGItLSV_3wS7grKuPTabL60BFnp88o';
return (
<SafeAreaView>
......
......@@ -11,19 +11,19 @@
44006126336D83DB220E7214 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
E7409E55B58E814834562CC9 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5114A1B6EF7A45CBC3B44888 /* libPods-example.a */; };
898CDE3ABB8AEDA46DE2D54C /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 03D0A3314F7CED31E3E4A63D /* libPods-example.a */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
03D0A3314F7CED31E3E4A63D /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = "<group>"; };
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
1A4D3A8ADA7BADEA4472F767 /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
5114A1B6EF7A45CBC3B44888 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
17135A107C9B30480C152E60 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
397BD168823606E82A9D6389 /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = example/AppDelegate.swift; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
A767065F2B7C703FC64B82F0 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
......@@ -32,7 +32,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E7409E55B58E814834562CC9 /* libPods-example.a in Frameworks */,
898CDE3ABB8AEDA46DE2D54C /* libPods-example.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -55,7 +55,7 @@
isa = PBXGroup;
children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
5114A1B6EF7A45CBC3B44888 /* libPods-example.a */,
03D0A3314F7CED31E3E4A63D /* libPods-example.a */,
);
name = Frameworks;
sourceTree = "<group>";
......@@ -92,8 +92,8 @@
BBD78D7AC51CEA395F1C20DB /* Pods */ = {
isa = PBXGroup;
children = (
1A4D3A8ADA7BADEA4472F767 /* Pods-example.debug.xcconfig */,
A767065F2B7C703FC64B82F0 /* Pods-example.release.xcconfig */,
397BD168823606E82A9D6389 /* Pods-example.debug.xcconfig */,
17135A107C9B30480C152E60 /* Pods-example.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
......@@ -105,13 +105,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */;
buildPhases = (
1DCE7F410965D5C781113361 /* [CP] Check Pods Manifest.lock */,
517A88A79CA5D0DA484A8A14 /* [CP] Check Pods Manifest.lock */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
C3A2FFFA13FFA1FBBEB4AA16 /* [CP] Embed Pods Frameworks */,
6DD180C10422588ED3399574 /* [CP] Copy Pods Resources */,
27513743F3A2F611B6B6CD11 /* [CP] Embed Pods Frameworks */,
C0419D3ABE4D41E88C3030E1 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
......@@ -183,7 +183,24 @@
shellPath = /bin/sh;
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
};
1DCE7F410965D5C781113361 /* [CP] Check Pods Manifest.lock */ = {
27513743F3A2F611B6B6CD11 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
517A88A79CA5D0DA484A8A14 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
......@@ -205,7 +222,7 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
6DD180C10422588ED3399574 /* [CP] Copy Pods Resources */ = {
C0419D3ABE4D41E88C3030E1 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
......@@ -222,23 +239,6 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n";
showEnvVarsInLog = 0;
};
C3A2FFFA13FFA1FBBEB4AA16 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
......@@ -255,7 +255,7 @@
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1A4D3A8ADA7BADEA4472F767 /* Pods-example.debug.xcconfig */;
baseConfigurationReference = 397BD168823606E82A9D6389 /* Pods-example.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
......@@ -283,7 +283,7 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A767065F2B7C703FC64B82F0 /* Pods-example.release.xcconfig */;
baseConfigurationReference = 17135A107C9B30480C152E60 /* Pods-example.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
......
{
"images" : [
{
"filename" : "closeinternal_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "closeowner_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "complete_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "drilldown__icon_transparent.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_handler_green.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_management_green.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_return_green.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_submitted_green.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_white_acessitem.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "lodge_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "new_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "notme_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "offlineunit_icon_green.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "pendingaccess_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "pendingitems_icon_green.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "pendingstart_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "poa_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "reassign_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "reject_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "void_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "wip_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "wipredo_notification_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -8,32 +8,32 @@
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
......
......@@ -6,7 +6,7 @@
<dict>
<key>Assets.car</key>
<data>
tiDJHgS+Mbu43+C6GiuoJR1rE/s=
apewM0kg8bkb0nA0BqxaEqt0L8I=
</data>
<key>Headers/QmsPlugin.h</key>
<data>
......@@ -31,7 +31,7 @@
<dict>
<key>hash2</key>
<data>
NzmSax3a+FRy3d2BvvftoEyaWVf17BzGCiO9/CkeCM8=
kujF94lp6x0Gv/ur/rYZEuwSRGB/AosKCC73EYwiL8g=
</data>
</dict>
<key>Headers/QmsPlugin.h</key>
......
......@@ -6,7 +6,7 @@
<dict>
<key>Assets.car</key>
<data>
tiDJHgS+Mbu43+C6GiuoJR1rE/s=
apewM0kg8bkb0nA0BqxaEqt0L8I=
</data>
<key>Headers/QmsPlugin.h</key>
<data>
......@@ -31,7 +31,7 @@
<dict>
<key>hash2</key>
<data>
NzmSax3a+FRy3d2BvvftoEyaWVf17BzGCiO9/CkeCM8=
kujF94lp6x0Gv/ur/rYZEuwSRGB/AosKCC73EYwiL8g=
</data>
</dict>
<key>Headers/QmsPlugin.h</key>
......
......@@ -10,6 +10,7 @@
2F8D09092E9605E200C764FF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F8D09082E9605E200C764FF /* CoreGraphics.framework */; };
2F99420D2EA9C5F000622199 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F99420C2EA9C5F000622199 /* QuartzCore.framework */; };
2FAEF09C2E8B7BD40086EDA3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FAEF09B2E8B7BD40086EDA3 /* Foundation.framework */; };
2FB266B52F1D1222009FDAE6 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FB266B42F1D1222009FDAE6 /* MessageUI.framework */; };
2FB2922A2EAB04F400D9F164 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FB292292EAB04F400D9F164 /* AVFoundation.framework */; };
2FB975E02ED7F9AA00E64A87 /* EventKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FB975DF2ED7F9AA00E64A87 /* EventKit.framework */; };
2FBC22B52EF93B8A00882B6F /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FBC22B42EF93B8A00882B6F /* UniformTypeIdentifiers.framework */; };
......@@ -52,6 +53,7 @@
2F99420C2EA9C5F000622199 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
2FAEF0992E8B7BC80086EDA3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.0.sdk/System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
2FAEF09B2E8B7BD40086EDA3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
2FB266B42F1D1222009FDAE6 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
2FB292292EAB04F400D9F164 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.0.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; };
2FB975DF2ED7F9AA00E64A87 /* EventKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EventKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.1.sdk/System/Library/Frameworks/EventKit.framework; sourceTree = DEVELOPER_DIR; };
2FBC22B42EF93B8A00882B6F /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
......@@ -118,6 +120,7 @@
2FB2922A2EAB04F400D9F164 /* AVFoundation.framework in Frameworks */,
2F99420D2EA9C5F000622199 /* QuartzCore.framework in Frameworks */,
2F8D09092E9605E200C764FF /* CoreGraphics.framework in Frameworks */,
2FB266B52F1D1222009FDAE6 /* MessageUI.framework in Frameworks */,
2FAEF09C2E8B7BD40086EDA3 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -156,6 +159,7 @@
2FAEF0982E8B7BC80086EDA3 /* Frameworks */ = {
isa = PBXGroup;
children = (
2FB266B42F1D1222009FDAE6 /* MessageUI.framework */,
2FC779BC2F0E33410002A1D4 /* MobileCoreServices.framework */,
2FBC22B62EF93BB400882B6F /* UIKit.framework */,
2FBC22B42EF93B8A00882B6F /* UniformTypeIdentifiers.framework */,
......
......@@ -32,6 +32,7 @@
[self setupItemsTable];
[self setupTermsSection];
[self setupRemarksSection];
[self updateItemsTableHeight];
}
- (void)viewDidLayoutSubviews {
......@@ -89,7 +90,7 @@
[self.scrollView.topAnchor constraintEqualToAnchor:self.header.bottomAnchor constant:10],
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
[self.contentView.topAnchor constraintEqualToAnchor:self.scrollView.topAnchor],
[self.contentView.leadingAnchor constraintEqualToAnchor:self.scrollView.leadingAnchor],
......@@ -121,27 +122,49 @@
card.layer.shadowOffset = CGSizeMake(0,2);
[self.contentView addSubview:card];
UILabel *unitNoLabel = [self regular16:[NSString stringWithFormat:@"Unit No: %@", self.unitID ?: @"--"]];
UILabel *unitOwnerLabel = [self regular16:[NSString stringWithFormat:@"Unit Owner: %@", self.transactionData[@"owner_name"] ?: @"--"]];
UILabel *unitNoTitle = [self regular16:@"Unit No.: "];
UILabel *unitOwnerTitle = [self regular16:@"Unit Owner: "];
UILabel *unitNoValue =
[self regular16:self.unitID ?: @"--"];
UILabel *unitOwnerValue =
[self regular16:self.transactionData[@"owner_name"] ?: @"--"];
unitNoValue.textColor = UIColor.blackColor;
unitOwnerValue.textColor = UIColor.blackColor;
[card addSubview:unitNoTitle];
[card addSubview:unitOwnerTitle];
[card addSubview:unitNoValue];
[card addSubview:unitOwnerValue];
[card addSubview:unitNoLabel];
[card addSubview:unitOwnerLabel];
CGFloat spacing = 8;
[NSLayoutConstraint activateConstraints:@[
[card.topAnchor constraintEqualToAnchor:title.bottomAnchor constant:8],
[card.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[card.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[unitNoLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:16],
[unitNoLabel.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16],
[unitNoLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-16],
// Title column
[unitNoTitle.topAnchor constraintEqualToAnchor:card.topAnchor constant:16],
[unitNoTitle.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16],
[unitOwnerLabel.topAnchor constraintEqualToAnchor:unitNoLabel.bottomAnchor constant:8],
[unitOwnerLabel.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16],
[unitOwnerLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-16],
[unitOwnerLabel.bottomAnchor constraintEqualToAnchor:card.bottomAnchor constant:-16]
]];
[unitOwnerTitle.topAnchor constraintEqualToAnchor:unitNoTitle.bottomAnchor constant:8],
[unitOwnerTitle.leadingAnchor constraintEqualToAnchor:unitNoTitle.leadingAnchor],
// 🔑 Same width → longest title wins
[unitOwnerTitle.widthAnchor constraintEqualToAnchor:unitNoTitle.widthAnchor],
// Value column
[unitNoValue.centerYAnchor constraintEqualToAnchor:unitNoTitle.centerYAnchor],
[unitNoValue.leadingAnchor constraintEqualToAnchor:unitNoTitle.trailingAnchor constant:spacing],
[unitNoValue.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-16],
[unitOwnerValue.centerYAnchor constraintEqualToAnchor:unitOwnerTitle.centerYAnchor],
[unitOwnerValue.leadingAnchor constraintEqualToAnchor:unitOwnerTitle.trailingAnchor constant:spacing],
[unitOwnerValue.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-16],
[unitOwnerValue.bottomAnchor constraintEqualToAnchor:card.bottomAnchor constant:-16],
]];
self.detailsCard = card;
}
......@@ -151,7 +174,7 @@
UILabel *itemsTitle = [[UILabel alloc] init];
itemsTitle.translatesAutoresizingMaskIntoConstraints = NO;
itemsTitle.font = [UIFont boldSystemFontOfSize:18];
itemsTitle.text = @"Items";
itemsTitle.text = @"Item List";
[self.contentView addSubview:itemsTitle];
// Table
......@@ -163,6 +186,10 @@
self.itemsTable.estimatedRowHeight = 44;
self.itemsTable.rowHeight = UITableViewAutomaticDimension;
self.itemsTable.separatorStyle = UITableViewCellSeparatorStyleNone; // we handle separators manually
self.itemsTable.layer.cornerRadius = 12;
self.itemsTable.layer.masksToBounds = YES;
self.itemsTable.layer.borderWidth = 0.5;
self.itemsTable.layer.borderColor = UIColor.lightGrayColor.CGColor;
[self.contentView addSubview:self.itemsTable];
// Table header
......@@ -357,8 +384,8 @@
submittedSignature.contentMode = UIViewContentModeScaleAspectFit;
submittedSignature.clipsToBounds = YES;
submittedSignature.layer.borderColor = UIColor.blackColor.CGColor;
submittedSignature.layer.borderWidth = 1.0;
submittedSignature.layer.cornerRadius = 4.0;
submittedSignature.layer.borderWidth = 0.5;
submittedSignature.layer.cornerRadius = 12;
submittedSignature.userInteractionEnabled = YES;
UITapGestureRecognizer *tapSubmitted = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapSignature:)];
[submittedSignature addGestureRecognizer:tapSubmitted];
......@@ -386,8 +413,8 @@
receivedSignature.contentMode = UIViewContentModeScaleAspectFit;
receivedSignature.clipsToBounds = YES;
receivedSignature.layer.borderColor = UIColor.blackColor.CGColor;
receivedSignature.layer.borderWidth = 1.0;
receivedSignature.layer.cornerRadius = 4.0;
receivedSignature.layer.borderWidth = 0.5;
receivedSignature.layer.cornerRadius = 12;
receivedSignature.userInteractionEnabled = YES;
UITapGestureRecognizer *tapReceived = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapSignature:)];
[receivedSignature addGestureRecognizer:tapReceived];
......@@ -405,23 +432,23 @@
[self.contentView addSubview:receivedDate];
// --- Constraints ---
CGFloat spacing = 8;
CGFloat spacing = 12;
[NSLayoutConstraint activateConstraints:@[
// Remarks
[self.remarksTitle.topAnchor constraintEqualToAnchor:self.htmlView.bottomAnchor constant:10],
[self.remarksTitle.topAnchor constraintEqualToAnchor:self.htmlView.bottomAnchor constant:24],
[self.remarksTitle.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[self.remarksText.topAnchor constraintEqualToAnchor:self.remarksTitle.bottomAnchor constant:spacing],
[self.remarksText.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[self.remarksText.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
// Submitted By
[submittedTitle.topAnchor constraintEqualToAnchor:self.remarksText.bottomAnchor constant:spacing*2],
[submittedTitle.topAnchor constraintEqualToAnchor:self.remarksText.bottomAnchor constant:24],
[submittedTitle.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[submittedSignature.topAnchor constraintEqualToAnchor:submittedTitle.bottomAnchor constant:spacing],
[submittedSignature.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[submittedSignature.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[submittedSignature.heightAnchor constraintEqualToConstant:180],
[submittedSignature.heightAnchor constraintEqualToConstant:140],
[submittedName.topAnchor constraintEqualToAnchor:submittedSignature.bottomAnchor constant:spacing],
[submittedName.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
......@@ -430,13 +457,13 @@
[submittedDate.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
// Received By
[receivedTitle.topAnchor constraintEqualToAnchor:submittedDate.bottomAnchor constant:spacing*2],
[receivedTitle.topAnchor constraintEqualToAnchor:submittedDate.bottomAnchor constant:24],
[receivedTitle.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[receivedSignature.topAnchor constraintEqualToAnchor:receivedTitle.bottomAnchor constant:spacing],
[receivedSignature.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[receivedSignature.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[receivedSignature.heightAnchor constraintEqualToConstant:180],
[receivedSignature.heightAnchor constraintEqualToConstant:140],
[receivedName.topAnchor constraintEqualToAnchor:receivedSignature.bottomAnchor constant:spacing],
[receivedName.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
......@@ -444,7 +471,7 @@
[receivedDate.topAnchor constraintEqualToAnchor:receivedName.bottomAnchor constant:spacing],
[receivedDate.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[receivedDate.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-40]
[receivedDate.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor]
]];
}
......@@ -609,4 +636,3 @@
}
@end
......@@ -94,12 +94,12 @@
[self.navBar.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.navBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.navBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.navBar.heightAnchor constraintEqualToConstant:50],
[self.navBar.heightAnchor constraintEqualToConstant:44],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.navBar.leadingAnchor constant:10],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.navBar.leadingAnchor constant:16],
[self.backButton.centerYAnchor constraintEqualToAnchor:self.navBar.centerYAnchor],
[self.backButton.widthAnchor constraintEqualToConstant:30],
[self.backButton.heightAnchor constraintEqualToConstant:30],
[self.backButton.widthAnchor constraintEqualToConstant:24],
[self.backButton.heightAnchor constraintEqualToConstant:24],
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.navBar.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.navBar.centerYAnchor],
......
......@@ -95,7 +95,7 @@
[self.headerBar.topAnchor constraintEqualToAnchor:safe.topAnchor],
[self.headerBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.headerBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.headerBar.heightAnchor constraintEqualToConstant:48]
[self.headerBar.heightAnchor constraintEqualToConstant:44]
]];
self.titleLabel = [[UILabel alloc] init];
......@@ -116,8 +116,8 @@
[NSLayoutConstraint activateConstraints:@[
[self.cancelButton.leadingAnchor constraintEqualToAnchor:self.headerBar.leadingAnchor constant:16],
[self.cancelButton.centerYAnchor constraintEqualToAnchor:self.headerBar.centerYAnchor],
[self.cancelButton.widthAnchor constraintEqualToConstant:36],
[self.cancelButton.heightAnchor constraintEqualToConstant:36],
[self.cancelButton.widthAnchor constraintEqualToConstant:24],
[self.cancelButton.heightAnchor constraintEqualToConstant:24],
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.headerBar.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.headerBar.centerYAnchor]
......@@ -125,8 +125,6 @@
}
- (void)setupScrollViewAndContent {
UILayoutGuide *safe = self.view.safeAreaLayoutGuide;
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.scrollView];
......
......@@ -133,7 +133,7 @@
[APIConfig setAuthTokem:self.user_token];
[APIConfig setClientId:self.ClientID];
// self.ClientCode = @"spt";
// self.ClientCode = @"spt";
[self requestCompanyCode];
}
......@@ -161,13 +161,11 @@
self.backButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.backButton];
[NSLayoutConstraint activateConstraints:@[
[self.headerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.headerView.heightAnchor constraintEqualToConstant:48],
[self.headerView.heightAnchor constraintEqualToConstant:44],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:8],
[self.backButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
......@@ -282,9 +280,17 @@
- (void)showLoadingOverlay:(NSString *)message {
if (!self.loadingOverlay) {
// Full screen overlay
self.loadingOverlay = [[UIView alloc] initWithFrame:self.view.bounds];
self.loadingOverlay = [[UIView alloc] init];
self.loadingOverlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
self.loadingOverlay.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.loadingOverlay.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.loadingOverlay];
[NSLayoutConstraint activateConstraints:@[
[self.loadingOverlay.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[self.loadingOverlay.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
[self.loadingOverlay.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.loadingOverlay.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
]];
// Spinner
self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
......@@ -318,8 +324,13 @@
}
- (void)hideLoadingOverlay {
dispatch_async(dispatch_get_main_queue(), ^{
[self.spinner stopAnimating];
[self.loadingOverlay removeFromSuperview];
self.spinner = nil;
self.loadingLabel = nil;
self.loadingOverlay = nil;
});
}
#pragma mark - API
......
......@@ -32,6 +32,8 @@
@property (nonatomic, strong) NSMutableArray<UIButton *> *uploadButtons;
@property (nonatomic, strong) NSMutableArray<UIImage *> *uploadedImages;
@property (nonatomic, assign) NSInteger activeUploadIndex;
@property (nonatomic, strong) UIStackView *imageStack;
@property (nonatomic, assign) BOOL hasExpandedImageUpload;
@property (nonatomic, strong) UIButton *mediaUploadButton;
@property (nonatomic, strong) NSURL *selectedMediaURL;
......@@ -47,6 +49,7 @@
self.uploadButtons = [NSMutableArray array];
self.uploadedImages = [NSMutableArray array];
self.activeUploadIndex = -1;
self.hasExpandedImageUpload = NO;
[self setupNavBar];
[self setupScrollView];
......@@ -61,6 +64,12 @@
self.reference);
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self addDashedBorderToView:self.mediaContainer];
[self addDashedBorderToView:self.imageContainer];
}
#pragma mark - UI Setup
- (void)setupNavBar {
self.navBar = [UIView new];
......@@ -117,31 +126,31 @@
self.imageUploadLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.imageContainer = [UIView new];
self.imageContainer.layer.borderWidth = 1.0;
self.imageContainer.layer.borderColor = [UIColor lightGrayColor].CGColor;
self.imageContainer.layer.borderWidth = 0;
self.imageContainer.layer.cornerRadius = 12;
self.imageContainer.clipsToBounds = NO;
self.imageContainer.translatesAutoresizingMaskIntoConstraints = NO;
UIStackView *uploadImageStack = [[UIStackView alloc] init];
uploadImageStack.axis = UILayoutConstraintAxisHorizontal;
uploadImageStack.spacing = 12;
uploadImageStack.distribution = UIStackViewDistributionFillEqually;
uploadImageStack.translatesAutoresizingMaskIntoConstraints = NO;
for (NSInteger i = 0; i < 2; i++) {
UIButton *box = [self makeUploadBox];
box.tag = 1000 + i;
[self.uploadButtons addObject:box];
[uploadImageStack addArrangedSubview:box];
}
self.imageStack = [[UIStackView alloc] init];
self.imageStack.axis = UILayoutConstraintAxisHorizontal;
self.imageStack.spacing = 12;
self.imageStack.distribution = UIStackViewDistributionFillEqually;
self.imageStack.layer.borderWidth = 0;
self.imageStack.translatesAutoresizingMaskIntoConstraints = NO;
[self.imageContainer addSubview:uploadImageStack];
UIButton *firstBox = [self makeUploadBox];
firstBox.tag = 1000;
firstBox.layer.borderWidth = 0;
[self.uploadButtons addObject:firstBox];
[self.imageStack addArrangedSubview:firstBox];
[self.imageContainer addSubview:self.imageStack];
[NSLayoutConstraint activateConstraints:@[
[uploadImageStack.topAnchor constraintEqualToAnchor:self.imageContainer.topAnchor constant:12],
[uploadImageStack.leadingAnchor constraintEqualToAnchor:self.imageContainer.leadingAnchor constant:12],
[uploadImageStack.trailingAnchor constraintEqualToAnchor:self.imageContainer.trailingAnchor constant:-12],
[uploadImageStack.bottomAnchor constraintEqualToAnchor:self.imageContainer.bottomAnchor constant:-12],
[self.imageStack.topAnchor constraintEqualToAnchor:self.imageContainer.topAnchor constant:12],
[self.imageStack.leadingAnchor constraintEqualToAnchor:self.imageContainer.leadingAnchor constant:12],
[self.imageStack.trailingAnchor constraintEqualToAnchor:self.imageContainer.trailingAnchor constant:-12],
[self.imageStack.bottomAnchor constraintEqualToAnchor:self.imageContainer.bottomAnchor constant:-12],
]];
self.mediaUploadLabel = [UILabel new];
......@@ -150,13 +159,14 @@
self.mediaUploadLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.mediaContainer = [UIView new];
self.mediaContainer.layer.borderWidth = 1.0;
self.mediaContainer.layer.borderColor = [UIColor lightGrayColor].CGColor;
self.mediaContainer.layer.cornerRadius = 12;
self.mediaContainer.layer.borderWidth = 0;
self.mediaContainer.translatesAutoresizingMaskIntoConstraints = NO;
self.mediaUploadButton = [self makeUploadBox];
self.mediaUploadButton.tag = 2000; // distinct namespace
self.mediaUploadButton.layer.borderWidth = 0; // remove button border
[self.mediaUploadButton setTitle:@"Choose Media" forState:UIControlStateNormal];
[self.mediaContainer addSubview:self.mediaUploadButton];
......@@ -169,8 +179,10 @@
]];
self.mediaRules = [UILabel new];
self.mediaRules.text = @"- Video duration should be 5 seconds or less.\n- Video file size should be nor more than 15MB.\n- Supported document format are .pdf, .docx, .xlsx, .csv.\n-Document file size should not be more than 15MB.";
self.mediaRules.text = @"- Video duration should be 5 seconds or less.\n- Video file size should not be more than 15MB.\n- Supported document format are .pdf, .docx, .xlsx, .csv.\n- Document file size should not be more than 15MB.";
self.mediaRules.font = [UIFont boldSystemFontOfSize:12];
self.mediaRules.numberOfLines = 0; // ✅ allow multiple lines
self.mediaRules.lineBreakMode = NSLineBreakByWordWrapping; // optional, default is fine
self.mediaRules.translatesAutoresizingMaskIntoConstraints = NO;
self.submitButton = [UIButton buttonWithType:UIButtonTypeSystem];
......@@ -202,9 +214,9 @@
[self.navBar.topAnchor constraintEqualToAnchor:safe.topAnchor],
[self.navBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.navBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.navBar.heightAnchor constraintEqualToConstant:48],
[self.navBar.heightAnchor constraintEqualToConstant:44],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.navBar.leadingAnchor constant:12],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.navBar.leadingAnchor constant:16],
[self.backButton.centerYAnchor constraintEqualToAnchor:self.navBar.centerYAnchor],
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.navBar.centerXAnchor],
......@@ -257,6 +269,7 @@
[self.mediaRules.topAnchor constraintEqualToAnchor:self.mediaContainer.bottomAnchor constant:12],
[self.mediaRules.leadingAnchor constraintEqualToAnchor:self.referenceLabel.leadingAnchor],
[self.mediaRules.trailingAnchor constraintEqualToAnchor:self.referenceLabel.trailingAnchor],
[self.submitButton.topAnchor constraintEqualToAnchor:self.mediaRules.bottomAnchor constant:40],
[self.submitButton.leadingAnchor constraintEqualToAnchor:self.referenceLabel.leadingAnchor],
......@@ -441,6 +454,11 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
[self.uploadedImages addObject:image];
}
// Expand layout after first successful image upload
if (self.uploadedImages.count == 1) {
[self expandImageUploadIfNeeded];
}
UIButton *button = self.uploadButtons[index];
if ([button isKindOfClass:[UIButton class]]) {
[button setTitle:nil forState:UIControlStateNormal];
......@@ -453,6 +471,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
button.imageEdgeInsets = UIEdgeInsetsZero;
[self addRemoveButtonToUpload:button atIndex:index];
[self addDashedBorderToView:self.imageContainer];
}
[picker dismissViewControllerAnimated:YES completion:nil];
......@@ -512,6 +531,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
// Remove the small "x" button
[sender removeFromSuperview];
[self collapseImageUploadIfNeeded];
}
#pragma mark - Actions
......@@ -694,4 +714,53 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
return [formatter stringFromDate:[NSDate date]];
}
- (void)addDashedBorderToView:(UIView *)view {
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = [UIColor lightGrayColor].CGColor;
shapeLayer.fillColor = UIColor.clearColor.CGColor;
shapeLayer.lineWidth = 1.5;
shapeLayer.lineDashPattern = @[@4, @3]; // dash length, gap length
shapeLayer.cornerRadius = view.layer.cornerRadius;
shapeLayer.frame = view.bounds;
shapeLayer.path =
[UIBezierPath bezierPathWithRoundedRect:view.bounds
cornerRadius:view.layer.cornerRadius].CGPath;
// Avoid duplicate dashed layers
for (CALayer *layer in view.layer.sublayers) {
if ([layer isKindOfClass:[CAShapeLayer class]]) {
[layer removeFromSuperlayer];
}
}
[view.layer addSublayer:shapeLayer];
}
- (void)expandImageUploadIfNeeded {
if (self.hasExpandedImageUpload) return;
UIButton *secondBox = [self makeUploadBox];
secondBox.tag = 1001;
secondBox.layer.borderWidth = 0;
[self.uploadButtons addObject:secondBox];
[self.imageStack addArrangedSubview:secondBox];
self.hasExpandedImageUpload = YES;
[UIView animateWithDuration:0.25 animations:^{
[self.imageStack layoutIfNeeded];
}];
}
- (void)collapseImageUploadIfNeeded {
if (!self.hasExpandedImageUpload) return;
UIButton *secondBox = self.uploadButtons.lastObject;
[self.imageStack removeArrangedSubview:secondBox];
[secondBox removeFromSuperview];
[self.uploadButtons removeLastObject];
self.hasExpandedImageUpload = NO;
}
@end
......@@ -377,23 +377,25 @@
[locationField.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
]];
// === Reselect Button (inside the container, right-aligned) ===
// UIButton *reselectBtn = [UIButton buttonWithType:UIButtonTypeSystem];
// reselectBtn.translatesAutoresizingMaskIntoConstraints = NO;
// [reselectBtn setTitle:@"Reselect" forState:UIControlStateNormal];
// [reselectBtn setTitleColor:[UIColor colorWithRed:0/255.0 green:109/255.0 blue:141/255.0 alpha:1]
// forState:UIControlStateNormal];
// reselectBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14];
// [reselectBtn addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside];
// [locationContainer addSubview:reselectBtn];
//
// [NSLayoutConstraint activateConstraints:@[
// [reselectBtn.trailingAnchor constraintEqualToAnchor:locationContainer.trailingAnchor constant:-8],
// [reselectBtn.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
//
// // shrink locationField width so it doesn’t overlap
// [locationField.trailingAnchor constraintEqualToAnchor:reselectBtn.leadingAnchor constant:-8],
// ]];
// === Reselect Button (inside the container, right-aligned) ===
UIButton *reselectBtn = [UIButton buttonWithType:UIButtonTypeSystem];
reselectBtn.translatesAutoresizingMaskIntoConstraints = NO;
[reselectBtn setTitle:@"Reselect" forState:UIControlStateNormal];
[reselectBtn setTitleColor:[UIColor colorWithRed:0/255.0 green:109/255.0 blue:141/255.0 alpha:1]
forState:UIControlStateNormal];
reselectBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14];
[reselectBtn addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside];
[locationContainer addSubview:reselectBtn];
[NSLayoutConstraint activateConstraints:@[
[reselectBtn.trailingAnchor constraintEqualToAnchor:locationContainer.trailingAnchor constant:-8],
[reselectBtn.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
[reselectBtn.heightAnchor constraintEqualToConstant:16],
[reselectBtn.widthAnchor constraintEqualToConstant:16],
// shrink locationField width so it doesn’t overlap
[locationField.leadingAnchor constraintEqualToAnchor:reselectBtn.trailingAnchor constant:8],
]];
// Category, Type, Issue — dropdown style
NSArray *titles = @[@"*Category", @"*Type", @"*Issue"];
......
......@@ -10,6 +10,7 @@
@property (nonatomic, strong) UIView *headerView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIView *titleContainer;
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UIButton *helpButton;
@property (nonatomic, strong) UIScrollView *scrollView;
......@@ -346,7 +347,7 @@
statusBarBackground.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:statusBarBackground];
// 🟦 Header background
// 🟦 Header background (only buttons now)
self.headerView = [[UIView alloc] init];
self.headerView.backgroundColor = statusBarBackground.backgroundColor;
self.headerView.translatesAutoresizingMaskIntoConstraints = NO;
......@@ -374,27 +375,24 @@
forControlEvents:UIControlEventTouchUpInside];
[self.headerView addSubview:self.helpButton];
// 🏷 Title label (project name)
// 🧩 Title label (project name) — now outside the header
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.titleLabel.text = self.projectName ?: @"Plan Viewer";
self.titleLabel.textColor = UIColor.whiteColor;
self.titleLabel.textColor = [UIColor whiteColor]; // maybe match your background
self.titleLabel.font = [UIFont boldSystemFontOfSize:20];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
[self.headerView addSubview:self.titleLabel];
self.titleLabel.textAlignment = NSTextAlignmentLeft;
// 🧩 Subtitle label (project code)
// 🏷 Subtitle label (project code) — also outside the header
UILabel *subtitleLabel = [[UILabel alloc] init];
subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
subtitleLabel.text = self.projectCode ?: @"";
subtitleLabel.textColor = [UIColor colorWithWhite:1.0 alpha:0.8];
subtitleLabel.textColor = [UIColor whiteColor];
subtitleLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightRegular];
subtitleLabel.textAlignment = NSTextAlignmentCenter;
[self.headerView addSubview:subtitleLabel];
subtitleLabel.textAlignment = NSTextAlignmentLeft;
// ✅ Constraints
UILayoutGuide *safe = self.view.safeAreaLayoutGuide;
CGFloat headerHeight = 110.0; // header height
[NSLayoutConstraint activateConstraints:@[
// Status bar background
......@@ -407,32 +405,54 @@
[self.headerView.topAnchor constraintEqualToAnchor:safe.topAnchor],
[self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.headerView.heightAnchor constraintEqualToConstant:headerHeight],
[self.headerView.heightAnchor constraintEqualToConstant:44],
// Back button
[self.backButton.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:8],
[self.backButton.topAnchor constraintEqualToAnchor:self.headerView.topAnchor constant:4],
[self.backButton.widthAnchor constraintEqualToConstant:44],
[self.backButton.heightAnchor constraintEqualToConstant:44],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:16],
[self.backButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.backButton.widthAnchor constraintEqualToConstant:24],
[self.backButton.heightAnchor constraintEqualToConstant:24],
// Help button
// [self.helpButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
// [self.helpButton.centerYAnchor constraintEqualToAnchor:self.backButton.centerYAnchor],
// [self.helpButton.widthAnchor constraintEqualToConstant:44],
// [self.helpButton.heightAnchor constraintEqualToConstant:44],
// Title label (below buttons, left-aligned)
[self.titleLabel.topAnchor constraintEqualToAnchor:self.backButton.bottomAnchor constant:4],
[self.titleLabel.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:16],
// [self.titleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.helpButton.leadingAnchor constant:-8],
// Subtitle (below title, left-aligned)
[subtitleLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:2],
[self.helpButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-16],
[self.helpButton.centerYAnchor constraintEqualToAnchor:self.backButton.centerYAnchor],
[self.helpButton.widthAnchor constraintEqualToConstant:24],
[self.helpButton.heightAnchor constraintEqualToConstant:24],
]];
// Container for title and subtitle
self.titleContainer = [[UIView alloc] init];
self.titleContainer.translatesAutoresizingMaskIntoConstraints = NO;
self.titleContainer.backgroundColor = self.headerView.backgroundColor; // same as header
[self.view addSubview:self.titleContainer];
// Move labels into this container
[self.titleContainer addSubview:self.titleLabel];
[self.titleContainer addSubview:subtitleLabel];
// Constraints
[NSLayoutConstraint activateConstraints:@[
// Container below header
[self.titleContainer.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor],
[self.titleContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.titleContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
// Optional: height based on labels
[self.titleContainer.bottomAnchor constraintEqualToAnchor:subtitleLabel.bottomAnchor constant:8],
// Title label
[self.titleLabel.topAnchor constraintEqualToAnchor:self.titleContainer.topAnchor constant:12],
[self.titleLabel.leadingAnchor constraintEqualToAnchor:self.titleContainer.leadingAnchor constant:16],
[self.titleLabel.trailingAnchor constraintEqualToAnchor:self.titleContainer.trailingAnchor constant:-16],
// Subtitle label
[subtitleLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:10],
[subtitleLabel.leadingAnchor constraintEqualToAnchor:self.titleLabel.leadingAnchor],
// [subtitleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.helpButton.leadingAnchor constant:-8],
[subtitleLabel.trailingAnchor constraintEqualToAnchor:self.titleLabel.trailingAnchor],
]];
}
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title
......@@ -443,7 +463,6 @@
});
}
- (void)createScrollView {
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.delegate = (id<UIScrollViewDelegate>)self;
......@@ -465,7 +484,7 @@
// ✅ Scroll view constraints (below header)
[NSLayoutConstraint activateConstraints:@[
[self.scrollView.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor],
[self.scrollView.topAnchor constraintEqualToAnchor:self.titleContainer.bottomAnchor],
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
......@@ -802,7 +821,7 @@
#pragma mark - Status Bar Style
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent; // ✅ White text/icons
return UIStatusBarStyleLightContent;
}
- (void)debugPrintAllIssues {
......
......@@ -84,7 +84,7 @@
- (void)setupContent {
UILabel *promptLabel = [[UILabel alloc] init];
promptLabel.translatesAutoresizingMaskIntoConstraints = NO;
promptLabel.text = @"Write your message:";
promptLabel.text = @"* Remarks";
promptLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
promptLabel.textColor = [UIColor darkGrayColor];
[self.view addSubview:promptLabel];
......@@ -155,7 +155,7 @@
[self.view addSubview:countLabel];
// Table showing list of issues
self.issuesTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleInsetGrouped];
self.issuesTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.issuesTable.translatesAutoresizingMaskIntoConstraints = NO;
self.issuesTable.dataSource = self;
self.issuesTable.delegate = self;
......@@ -372,7 +372,7 @@
cell.detailTextLabel.text = @"";
}
cell.backgroundColor = [UIColor whiteColor];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor blackColor];
cell.detailTextLabel.textColor = [UIColor colorWithWhite:0.4 alpha:1.0];
cell.contentView.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0];
......@@ -387,7 +387,7 @@
cell.textLabel.font = [UIFont boldSystemFontOfSize:15];
cell.detailTextLabel.font = [UIFont systemFontOfSize:13];
cell.textLabel.textColor = [UIColor colorWithRed:0.0 green:0.43 blue:0.55 alpha:1.0];
cell.textLabel.textColor = [UIColor blackColor];
cell.detailTextLabel.textColor = [UIColor darkGrayColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
......
// HistoryDetailsViewController.mm
#import "HistoryDetailsViewController.h"
#import "SyncPendingShareHelper.h"
@interface HistoryDetailsViewController ()
@property (nonatomic, strong) UIView *headerView;
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *shareButton;
@property (nonatomic, strong) NSArray<NSDictionary *> *itemsToShare; // <-- Add this
@end
......@@ -50,6 +53,19 @@
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.titleLabel];
self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.shareButton setTitle:@"Share to Email" forState:UIControlStateNormal];
[self.shareButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
self.shareButton.layer.borderColor = UIColor.whiteColor.CGColor;
self.shareButton.layer.borderWidth = 0.5;
self.shareButton.layer.cornerRadius = 14;
[self.shareButton addTarget:self
action:@selector(onShare)
forControlEvents:UIControlEventTouchUpInside];
self.shareButton.titleLabel.font = [UIFont systemFontOfSize:14];
self.shareButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.shareButton];
[NSLayoutConstraint activateConstraints:@[
[self.headerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
......@@ -63,6 +79,11 @@
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.headerView.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.shareButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-16],
[self.shareButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.shareButton.heightAnchor constraintEqualToConstant:28],
[self.shareButton.widthAnchor constraintEqualToConstant:120],
]];
}
......@@ -204,4 +225,35 @@
return UIColor.labelColor;
}
- (NSArray<NSDictionary *> *)prepareItemsForSharing {
NSMutableArray<NSDictionary *> *shareItems = [NSMutableArray array];
// If you want to share a single item:
if (self.itemData) {
[shareItems addObject:self.itemData];
}
// Or, if you have multiple items stored in itemsToShare:
if (self.itemsToShare.count > 0) {
[shareItems addObjectsFromArray:self.itemsToShare];
}
return shareItems;
}
- (void)onShare {
NSArray<NSDictionary *> *shareItems = [self prepareItemsForSharing];
if (shareItems.count == 0) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"No items"
message:@"There are no items to share."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
return;
}
[SyncPendingShareHelper sharePendingItems:shareItems
fromController:self];
}
@end
......@@ -3,6 +3,7 @@
#import "SyncPendingViewController.h"
#import "PendingDetailsViewController.h"
#import "OfflineSyncManager.h"
#import "SyncPendingShareHelper.h"
typedef NS_ENUM(NSInteger, SyncPendingViewMode) {
SyncPendingViewModeList,
......@@ -46,9 +47,9 @@ typedef NS_ENUM(NSInteger, SyncPendingViewMode) {
[self.contentView addSubview:self.cardView];
self.unitLabel = [self makeLabel:16 bold:YES];
self.createdByLabel = [self makeLabel:13 bold:NO];
self.createdOnLabel = [self makeLabel:13 bold:NO];
self.actionLabel = [self makeLabel:13 bold:NO];
self.createdByLabel = [self makeLabel:14 bold:NO];
self.createdOnLabel = [self makeLabel:14 bold:NO];
self.actionLabel = [self makeLabel:14 bold:NO];
UIStackView *stack = [[UIStackView alloc] initWithArrangedSubviews:@[
self.unitLabel,
......@@ -58,21 +59,21 @@ typedef NS_ENUM(NSInteger, SyncPendingViewMode) {
]];
stack.axis = UILayoutConstraintAxisVertical;
stack.spacing = 4;
stack.spacing = 12;
stack.translatesAutoresizingMaskIntoConstraints = NO;
[self.cardView addSubview:stack];
[NSLayoutConstraint activateConstraints:@[
[self.cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:8],
[self.cardView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-8],
[self.cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:12],
[self.cardView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-12],
[self.cardView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[self.cardView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[self.cardView.heightAnchor constraintEqualToConstant:150],
[stack.topAnchor constraintEqualToAnchor:self.cardView.topAnchor constant:12],
[stack.bottomAnchor constraintEqualToAnchor:self.cardView.bottomAnchor constant:-12],
[stack.leadingAnchor constraintEqualToAnchor:self.cardView.leadingAnchor constant:12],
[stack.trailingAnchor constraintEqualToAnchor:self.cardView.trailingAnchor constant:-12],
]];
}
return self;
......@@ -117,6 +118,8 @@ typedef NS_ENUM(NSInteger, SyncPendingViewMode) {
@property (nonatomic, assign) BOOL isLoading;
@property (nonatomic, strong) NSArray<NSDictionary *> *arrayPendingItems;
@end
@interface ProjectSectionHeaderView : UIView
......@@ -196,37 +199,37 @@ typedef NS_ENUM(NSInteger, SyncPendingViewMode) {
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.titleLabel];
// self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem];
// [self.shareButton setTitle:@"Share to Email" forState:UIControlStateNormal];
// [self.shareButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
// self.shareButton.layer.borderColor = UIColor.whiteColor.CGColor;
// self.shareButton.layer.borderWidth = 0.5;
// self.shareButton.layer.cornerRadius = 14;
// [self.shareButton addTarget:self
// action:@selector(onShare)
// forControlEvents:UIControlEventTouchUpInside];
// self.shareButton.titleLabel.font = [UIFont systemFontOfSize:14];
// self.shareButton.translatesAutoresizingMaskIntoConstraints = NO;
// [self.headerView addSubview:self.shareButton];
self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.shareButton setTitle:@"Share to Email" forState:UIControlStateNormal];
[self.shareButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
self.shareButton.layer.borderColor = UIColor.whiteColor.CGColor;
self.shareButton.layer.borderWidth = 0.5;
self.shareButton.layer.cornerRadius = 14;
[self.shareButton addTarget:self
action:@selector(onShare)
forControlEvents:UIControlEventTouchUpInside];
self.shareButton.titleLabel.font = [UIFont systemFontOfSize:14];
self.shareButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.shareButton];
[NSLayoutConstraint activateConstraints:@[
[self.headerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.headerView.heightAnchor constraintEqualToConstant:48],
[self.headerView.heightAnchor constraintEqualToConstant:44],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:8],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:16],
[self.backButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.backButton.widthAnchor constraintEqualToConstant:32],
[self.backButton.heightAnchor constraintEqualToConstant:32],
[self.backButton.widthAnchor constraintEqualToConstant:24],
[self.backButton.heightAnchor constraintEqualToConstant:24],
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.headerView.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
// [self.shareButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
// [self.shareButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
// [self.shareButton.heightAnchor constraintEqualToConstant:28],
// [self.shareButton.widthAnchor constraintEqualToConstant:120],
[self.shareButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
[self.shareButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.shareButton.heightAnchor constraintEqualToConstant:28],
[self.shareButton.widthAnchor constraintEqualToConstant:120],
]];
}
......@@ -256,16 +259,28 @@ typedef NS_ENUM(NSInteger, SyncPendingViewMode) {
#pragma mark - Data
- (void)loadPendingData {
NSArray *pending =
[[OfflineSyncManager shared] pendingItemsForUI];
NSArray *pending = [[OfflineSyncManager shared] pendingItemsForUI];
NSLog(@"🖥 [SyncPendingVC] Pending sections: %@", pending);
if (pending.count > 0) {
self.sections = pending;
// Flatten all items into arrayPendingItems for sharing
NSMutableArray *allItems = [NSMutableArray array];
for (NSDictionary *section in pending) {
[allItems addObjectsFromArray:section[@"items"]];
}
self.arrayPendingItems = allItems;
} else {
[self setupDummyData];
// Flatten dummy items too
NSMutableArray *allItems = [NSMutableArray array];
for (NSDictionary *section in self.sections) {
[allItems addObjectsFromArray:section[@"items"]];
}
self.arrayPendingItems = allItems;
}
[self reloadUI];
......@@ -374,23 +389,8 @@ heightForHeaderInSection:(NSInteger)section {
}
- (void)onShare {
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:@"Share Pending Items"
message:@"Send pending items to email?"
preferredStyle:UIAlertControllerStyleActionSheet];
[alert addAction:[UIAlertAction actionWithTitle:@"Send"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"Share triggered (stub)");
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
[SyncPendingShareHelper sharePendingItems:self.arrayPendingItems
fromController:self];
}
- (UIView *)emptyStateView {
......@@ -415,4 +415,7 @@ heightForHeaderInSection:(NSInteger)section {
self.view.userInteractionEnabled = !isLoading;
}
@end
......@@ -83,41 +83,31 @@
return;
}
// ✅ Construct URL (with token)
NSURL *url = [APIConfig urlWithPath:@"/framework/owner/plan/getLocationByUnit"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
// 🧱 multipart/form-data setup (same as requestAnnouncement)
NSString *boundary = [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
NSMutableData *body = [NSMutableData data];
// 👇 Helper block to add form fields
void (^appendFormField)(NSString *, NSString *) = ^(NSString *key, NSString *value) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:
@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", value]
dataUsingEncoding:NSUTF8StringEncoding]];
NSDictionary *jsonBody = @{
@"data": @{
@"os": [APIConfig os] ,
@"drawing_plan_id": [APIConfig drawingPlanId] ?: @"",
}
};
// 🧩 Add POST fields
appendFormField(@"data[os]", [APIConfig os] );
appendFormField(@"data[drawing_plan_id]",[APIConfig drawingPlanId] );
NSLog(@"🌍 SUBMIT URL: %@", url.absoluteString);
NSLog(@"📦 SUBMIT Body JSON: %@", jsonBody);
// You can reuse your existing getDeviceInfo() method to produce this JSON string
NSString *deviceInfo = [APIConfig deviceInfoJSONString];
appendFormField(@"data[information]", deviceInfo);
NSError *jsonError;
NSData *body = [NSJSONSerialization dataWithJSONObject:jsonBody options:0 error:&jsonError];
// 🔚 End boundary
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
if (jsonError) {
NSLog(@"❌ JSON Serialization Error: %@", jsonError);
if (completion) completion(NO, nil, jsonError);
return;
}
request.HTTPBody = body;
// 🌍 Debug logs
......
// SyncPendingShareHelper.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface SyncPendingShareHelper : NSObject
+ (void)sharePendingItems:(NSArray<NSDictionary *> *)items
fromController:(UIViewController *)controller;
@end
NS_ASSUME_NONNULL_END
// SyncPendingShareHelper.mm
#import "SyncPendingShareHelper.h"
#import <CommonCrypto/CommonCryptor.h>
#import <MessageUI/MessageUI.h>
@interface SyncPendingShareHelper () <MFMailComposeViewControllerDelegate>
@property (nonatomic, weak) UIViewController *presentingController;
@end
@implementation SyncPendingShareHelper
+ (void)sharePendingItems:(NSArray<NSDictionary *> *)items
fromController:(UIViewController *)controller {
if (!items || items.count == 0) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"No Data"
message:@"There are no pending items to share."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[controller presentViewController:alert animated:YES completion:nil];
return;
}
SyncPendingShareHelper *helper = [SyncPendingShareHelper new];
helper.presentingController = controller;
[helper prepareAndShareItems:items];
}
- (void)prepareAndShareItems:(NSArray<NSDictionary *> *)items {
NSError *error = nil;
// Paths
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *issueFile = [documentsPath stringByAppendingPathComponent:@"all_pending_issue_data.txt"];
NSString *encryptFile = [documentsPath stringByAppendingPathComponent:@"all_pending_issue_data_encrypt.txt"];
// Write JSON
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:items options:NSJSONWritingPrettyPrinted error:&error];
if (error) { NSLog(@"JSON Serialization error: %@", error); return; }
[jsonData writeToFile:issueFile atomically:YES];
// AES-128-CBC Encryption
NSString *keyString = @"mySecretKey12345"; // 16 chars
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
NSData *dataToEncrypt = jsonData;
uint8_t ivBytes[kCCBlockSizeAES128];
if (SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivBytes) != errSecSuccess) { NSLog(@"Failed IV"); return; }
NSData *ivData = [NSData dataWithBytes:ivBytes length:kCCBlockSizeAES128];
size_t outLength;
NSMutableData *cipherData = [NSMutableData dataWithLength:dataToEncrypt.length + kCCBlockSizeAES128];
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyData.bytes,
kCCKeySizeAES128,
ivData.bytes,
dataToEncrypt.bytes,
dataToEncrypt.length,
cipherData.mutableBytes,
cipherData.length,
&outLength);
if (cryptStatus != kCCSuccess) { NSLog(@"Encryption failed: %d", cryptStatus); return; }
cipherData.length = outLength;
NSString *ivBase64 = [ivData base64EncodedStringWithOptions:0];
NSString *cipherBase64 = [cipherData base64EncodedStringWithOptions:0];
NSString *finalEncryptedString = [NSString stringWithFormat:@"%@:%@", ivBase64, cipherBase64];
[finalEncryptedString writeToFile:encryptFile atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (error) { NSLog(@"Failed to write encrypted file: %@", error); return; }
// Present Mail
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailVC = [[MFMailComposeViewController alloc] init];
mailVC.mailComposeDelegate = self;
[mailVC setSubject:@"QMS Owner - Sync Troubleshoot Log"];
[mailVC setToRecipients:@[@"support@convep.com"]];
[mailVC setMessageBody:@"Attached are the log file and encrypted data for reference." isHTML:NO];
NSData *issueData = [NSData dataWithContentsOfFile:issueFile];
NSData *encryptData = [NSData dataWithContentsOfFile:encryptFile];
[mailVC addAttachmentData:issueData mimeType:@"text/plain" fileName:@"all_pending_issue_data.txt"];
[mailVC addAttachmentData:encryptData mimeType:@"text/plain" fileName:@"all_pending_issue_data_encrypt.txt"];
[self.presentingController presentViewController:mailVC animated:YES completion:nil];
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error"
message:@"Mail services are not available."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self.presentingController presentViewController:alert animated:YES completion:nil];
}
}
// Mail delegate
- (void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError *)error {
[controller dismissViewControllerAnimated:YES completion:nil];
if (error) NSLog(@"Mail send error: %@", error);
}
@end
......@@ -8,32 +8,32 @@
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
......
......@@ -6,7 +6,7 @@
<dict>
<key>Assets.car</key>
<data>
tiDJHgS+Mbu43+C6GiuoJR1rE/s=
apewM0kg8bkb0nA0BqxaEqt0L8I=
</data>
<key>Headers/QmsPlugin.h</key>
<data>
......@@ -31,7 +31,7 @@
<dict>
<key>hash2</key>
<data>
NzmSax3a+FRy3d2BvvftoEyaWVf17BzGCiO9/CkeCM8=
kujF94lp6x0Gv/ur/rYZEuwSRGB/AosKCC73EYwiL8g=
</data>
</dict>
<key>Headers/QmsPlugin.h</key>
......
......@@ -6,7 +6,7 @@
<dict>
<key>Assets.car</key>
<data>
tiDJHgS+Mbu43+C6GiuoJR1rE/s=
apewM0kg8bkb0nA0BqxaEqt0L8I=
</data>
<key>Headers/QmsPlugin.h</key>
<data>
......@@ -31,7 +31,7 @@
<dict>
<key>hash2</key>
<data>
NzmSax3a+FRy3d2BvvftoEyaWVf17BzGCiO9/CkeCM8=
kujF94lp6x0Gv/ur/rYZEuwSRGB/AosKCC73EYwiL8g=
</data>
</dict>
<key>Headers/QmsPlugin.h</key>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment