mirror of
https://github.com/anonfaded/FadCam.git
synced 2026-03-13 09:00:17 +08:00
feat: Update video element styles for improved layout and accessibility; enhance build script for device installation and launching
This commit is contained in:
@@ -1975,7 +1975,7 @@ video {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
min-height: 38px;
|
||||
min-height: 48px;
|
||||
transition: border-color 200ms ease;
|
||||
}
|
||||
|
||||
@@ -1987,6 +1987,9 @@ video {
|
||||
position: relative;
|
||||
padding: 10px 12px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* Background Fill - Yellow when ON */
|
||||
@@ -2016,15 +2019,15 @@ video {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* Icon Container */
|
||||
/* Icon Container – proportional to card height */
|
||||
.torch-icon-fa {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 20px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 24px;
|
||||
flex-shrink: 0;
|
||||
color: #8b949e;
|
||||
transition: color 300ms ease;
|
||||
line-height: 20px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -2033,12 +2036,13 @@ video {
|
||||
text-shadow: 0 0 8px rgba(255, 215, 0, 0.8), 0 0 4px rgba(255, 215, 0, 0.6);
|
||||
}
|
||||
|
||||
/* Text Container */
|
||||
/* Text Container – ensure text doesn't wrap */
|
||||
.torch-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.torch-label {
|
||||
@@ -2365,26 +2369,40 @@ video {
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
/* Exposure compact card (2-row: icon+label top, buttons bottom) */
|
||||
/* Exposure compact card - match other cards (horizontal layout) */
|
||||
.exposure-card {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 5px;
|
||||
cursor: default;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
.exp-top-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Align +/- buttons under the text (icon 18px + gap 8px = 26px indent) */
|
||||
/* Buttons should be aligned right, match torch-value spacing */
|
||||
.exp-btn-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding-left: 26px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.exposure-icon-fa {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 24px;
|
||||
flex-shrink: 0;
|
||||
color: #8b949e;
|
||||
transition: color 200ms ease;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.exposure-label-group {
|
||||
@@ -2647,42 +2665,45 @@ input[type="range"].zoom-slider {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* M3 thumb – 20dp circle, elevation shadow, no border */
|
||||
/* M3 thumb – 16dp bar/pill (Material 3 label slider style), elevation shadow, no border */
|
||||
input[type="range"].zoom-slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
border-radius: 2px;
|
||||
background: #ef5350;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.55), 0 1px 2px rgba(0, 0, 0, 0.35);
|
||||
transition: box-shadow 200ms cubic-bezier(0.2, 0, 0, 1);
|
||||
}
|
||||
|
||||
/* M3 hover state layer */
|
||||
/* M3 hover state layer (bar style) */
|
||||
input[type="range"].zoom-slider:hover::-webkit-slider-thumb {
|
||||
box-shadow: 0 0 0 8px rgba(239, 83, 80, 0.12),
|
||||
width: 6px;
|
||||
box-shadow: 0 0 0 6px rgba(239, 83, 80, 0.12),
|
||||
0 1px 3px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
/* M3 focus state layer */
|
||||
/* M3 focus state layer (bar style) */
|
||||
input[type="range"].zoom-slider:focus::-webkit-slider-thumb {
|
||||
box-shadow: 0 0 0 10px rgba(239, 83, 80, 0.14),
|
||||
width: 6px;
|
||||
box-shadow: 0 0 0 8px rgba(239, 83, 80, 0.14),
|
||||
0 1px 3px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
/* M3 pressed state layer */
|
||||
/* M3 pressed state layer (bar style) */
|
||||
input[type="range"].zoom-slider:active::-webkit-slider-thumb {
|
||||
box-shadow: 0 0 0 12px rgba(239, 83, 80, 0.18),
|
||||
width: 6px;
|
||||
box-shadow: 0 0 0 10px rgba(239, 83, 80, 0.18),
|
||||
0 1px 3px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
/* Firefox – M3 bar style */
|
||||
input[type="range"].zoom-slider::-moz-range-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
border-radius: 2px;
|
||||
background: #ef5350;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
@@ -2725,6 +2746,13 @@ input[type="range"].zoom-slider::-moz-range-progress {
|
||||
.zoom-reset-btn:active {
|
||||
transform: scale(0.90);
|
||||
}
|
||||
.zoom-reset-btn:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
color: #443d3d;
|
||||
border-color: transparent;
|
||||
background: #0d1117;
|
||||
}
|
||||
|
||||
/* -------- NETWORK CARD -------- */
|
||||
|
||||
|
||||
@@ -455,7 +455,7 @@
|
||||
onchange="onZoomSliderCommit(this.value)">
|
||||
</div>
|
||||
<button class="zoom-reset-btn" onclick="resetZoom()" title="Reset zoom">
|
||||
<i class="fas fa-compress-alt"></i>
|
||||
<i class="fas fa-undo"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -2297,6 +2297,9 @@
|
||||
if (el) el.textContent = v.toFixed(1) + '×';
|
||||
// Pan container visible only when zoom > 1
|
||||
document.getElementById('panContainer')?.classList.toggle('visible', v > 1.0);
|
||||
// Reset button only enabled when zoom !== 1.0
|
||||
const resetBtn = document.querySelector('.zoom-reset-btn');
|
||||
if (resetBtn) resetBtn.disabled = (Math.abs(v - 1.0) < 0.01); // Account for float precision
|
||||
// Update filled-track CSS variable
|
||||
const slider = document.getElementById('zoomSlider');
|
||||
if (slider) {
|
||||
@@ -2417,7 +2420,7 @@
|
||||
const el = document.getElementById('exposureValue');
|
||||
// Show target value as visual feedback (like torch shows intended state)
|
||||
if (el) el.textContent = (targetEv > 0 ? '+' : '') + targetEv;
|
||||
executingState.start('exposureCompensation', targetEv, '.exposure-card');
|
||||
executingState.start('exposureCompensation', targetEv, '#exposureCard');
|
||||
try {
|
||||
await dashboardViewModel.setExposure(targetEv);
|
||||
_currentEv = targetEv; // Mark confirmed locally too
|
||||
|
||||
76
build.sh
76
build.sh
@@ -258,83 +258,55 @@ execute_build() {
|
||||
print_status "💾" "Size: ${BRIGHT_RED}${APK_SIZE}${RESET}"
|
||||
echo ""
|
||||
|
||||
# Install if requested using Gradle (handles all connected devices automatically)
|
||||
# Install if requested using Gradle (professional Android approach)
|
||||
if [ "$INSTALL" = "true" ]; then
|
||||
|
||||
# Get list of connected devices and show all with model/version
|
||||
local DEVICES=()
|
||||
while read -r line; do
|
||||
# Parse device ID and status from adb devices output
|
||||
local device_id=$(echo "$line" | awk '{print $1}')
|
||||
local device_status=$(echo "$line" | awk '{print $2}')
|
||||
if [ "$device_status" = "device" ] && [ -n "$device_id" ]; then
|
||||
DEVICES+=("$device_id")
|
||||
fi
|
||||
done < <(adb devices | tail -n +2)
|
||||
|
||||
local DEVICE_COUNT=${#DEVICES[@]}
|
||||
# Capitalize first letter of BUILD_TYPE for Gradle task (e.g., debug -> Debug)
|
||||
local BUILD_TYPE_UPPER=$(echo "$BUILD_TYPE" | tr '[:lower:]' '[:upper:]' | cut -c1)$(echo "$BUILD_TYPE" | cut -c2-)
|
||||
|
||||
# Show device info using standard adb approach
|
||||
local DEVICE_COUNT=$(adb devices | grep -E '^[a-zA-Z0-9].*[[:space:]]device$' | wc -l)
|
||||
if [ $DEVICE_COUNT -eq 0 ]; then
|
||||
print_status "⚠️" "No connected devices found"
|
||||
echo ""
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
||||
print_status "📱" "Connected Devices: ${BRIGHT_RED}${DEVICE_COUNT}${RESET}"
|
||||
for ((i=0; i<DEVICE_COUNT; i++)); do
|
||||
local device="${DEVICES[$i]}"
|
||||
local DEVICE_MODEL=$(adb -s "$device" shell getprop ro.product.model 2>/dev/null | tr -d '\r' | xargs || echo "Unknown")
|
||||
local DEVICE_VERSION=$(adb -s "$device" shell getprop ro.build.version.release 2>/dev/null | tr -d '\r' | xargs || echo "?")
|
||||
printf " ${BRIGHT_RED}[%d/%d]${RESET} ${GRAY}%s${RESET} - ${WHITE}%s (Android %s)${RESET}\n" $((i+1)) $DEVICE_COUNT "$device" "$DEVICE_MODEL" "$DEVICE_VERSION"
|
||||
adb devices | grep -E '^[a-zA-Z0-9].*[[:space:]]device$' | while read -r device _; do
|
||||
local DEVICE_MODEL=$(adb -s "$device" shell getprop ro.product.model 2>/dev/null || echo "Unknown")
|
||||
local DEVICE_VERSION=$(adb -s "$device" shell getprop ro.build.version.release 2>/dev/null || echo "?")
|
||||
echo -e " ${BRIGHT_RED}[${device:0:16}]${RESET} ${WHITE}${DEVICE_MODEL}${RESET} - ${GRAY}Android ${DEVICE_VERSION}${RESET}"
|
||||
done
|
||||
echo ""
|
||||
|
||||
print_status "📥" "Installing to all connected devices..."
|
||||
echo ""
|
||||
|
||||
# Capitalize first letter of BUILD_TYPE for Gradle task (e.g., debug -> Debug)
|
||||
local BUILD_TYPE_UPPER=$(echo "$BUILD_TYPE" | tr '[:lower:]' '[:upper:]' | cut -c1)$(echo "$BUILD_TYPE" | cut -c2-)
|
||||
# Use gradle's standard install task (Android official way)
|
||||
local INSTALL_TASK="app:installDefault${BUILD_TYPE_UPPER}"
|
||||
local INSTALL_LOG=$(mktemp)
|
||||
|
||||
if ./gradlew "$INSTALL_TASK" --no-daemon --quiet > "$INSTALL_LOG" 2>&1; then
|
||||
if ./gradlew "$INSTALL_TASK" --no-daemon 2>&1 | tail -3; then
|
||||
print_status "✅" "Installation successful on ${BRIGHT_RED}${DEVICE_COUNT}${RESET} device(s)"
|
||||
|
||||
# Launch using Android's official am start command (not gradle run which doesn't exist)
|
||||
echo ""
|
||||
print_status "🚀" "Launching app on all devices..."
|
||||
local LAUNCH_SUCCESS=0
|
||||
# Determine package name based on build type
|
||||
|
||||
local PACKAGE_NAME="com.fadcam.beta"
|
||||
if [ "$BUILD_TYPE" = "release" ]; then
|
||||
PACKAGE_NAME="com.fadcam"
|
||||
fi
|
||||
for ((i=0; i<DEVICE_COUNT; i++)); do
|
||||
local device="${DEVICES[$i]}"
|
||||
local DEVICE_MODEL=$(adb -s "$device" shell getprop ro.product.model 2>/dev/null | tr -d '\r' | xargs || echo "Unknown")
|
||||
if adb -s "$device" shell am start -n "${PACKAGE_NAME}/com.fadcam.SplashActivity" >/dev/null 2>&1; then
|
||||
echo -e " ${BRIGHT_RED}[${device}]${RESET} ${WHITE}${DEVICE_MODEL}${RESET} - ✅ Launched"
|
||||
((LAUNCH_SUCCESS++))
|
||||
[ "$BUILD_TYPE" = "release" ] && PACKAGE_NAME="com.fadcam"
|
||||
|
||||
# Use am start with proper activity path - this is the Android standard
|
||||
adb devices | grep -E '^[a-zA-Z0-9].*[[:space:]]device$' | while read -r device _; do
|
||||
# Launch the app (Android's official way) - note: full class path needed
|
||||
if adb -s "$device" shell am start -W -n "${PACKAGE_NAME}/com.fadcam.SplashActivity" 2>/dev/null; then
|
||||
echo -e " ${BRIGHT_RED}[${device:0:16}]${RESET} ✅ Launched successfully"
|
||||
else
|
||||
echo -e " ${BRIGHT_RED}[${device}]${RESET} ${WHITE}${DEVICE_MODEL}${RESET} - ❌ Failed to launch"
|
||||
echo -e " ${BRIGHT_RED}[${device:0:16}]${RESET} ⚠️ Launch may have failed"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $LAUNCH_SUCCESS -gt 0 ]; then
|
||||
print_status "✅" "App launched on ${BRIGHT_RED}${LAUNCH_SUCCESS}/${DEVICE_COUNT}${RESET} device(s)"
|
||||
else
|
||||
print_status "⚠️" "Could not launch app on any device"
|
||||
fi
|
||||
else
|
||||
print_status "❌" "Installation failed"
|
||||
echo ""
|
||||
echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
|
||||
echo -e "${BRIGHT_RED}Installation Error:${RESET}"
|
||||
echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
|
||||
cat "$INSTALL_LOG"
|
||||
echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
|
||||
rm -f "$INSTALL_LOG"
|
||||
echo ""
|
||||
return 1
|
||||
fi
|
||||
rm -f "$INSTALL_LOG"
|
||||
else
|
||||
print_status "💡" "APK ready: ${BRIGHT_RED}${APK_PATH}${RESET}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user