Update.
This commit is contained in:
parent
6950455bbf
commit
24385839c4
8
Makefile
8
Makefile
@ -45,7 +45,7 @@ dev:
|
|||||||
|
|
||||||
run:
|
run:
|
||||||
@echo "Starting MyWebdav application..."
|
@echo "Starting MyWebdav application..."
|
||||||
@echo "Access the application at http://localhost:8000"
|
@echo "Access the application at http://localhost:9004"
|
||||||
$(PYTHON) -m mywebdav.main
|
$(PYTHON) -m mywebdav.main
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@ -147,9 +147,9 @@ setup: setup-env install dev init-db
|
|||||||
@echo "Next steps:"
|
@echo "Next steps:"
|
||||||
@echo " 1. Update .env with your configuration (especially Stripe keys)"
|
@echo " 1. Update .env with your configuration (especially Stripe keys)"
|
||||||
@echo " 2. Run 'make run' or 'make all' to start the application"
|
@echo " 2. Run 'make run' or 'make all' to start the application"
|
||||||
@echo " 3. Access the application at http://localhost:8000"
|
@echo " 3. Access the application at http://localhost:9004"
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
@echo "Generating API documentation..."
|
@echo "Generating API documentation..."
|
||||||
@echo "API documentation available at http://localhost:8000/docs when running"
|
@echo "API documentation available at http://localhost:9004/docs when running"
|
||||||
@echo "ReDoc available at http://localhost:8000/redoc when running"
|
@echo "ReDoc available at http://localhost:9004/redoc when running"
|
||||||
|
|||||||
@ -315,7 +315,7 @@ def main():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--host", type=str, default="0.0.0.0", help="Host address to bind to"
|
"--host", type=str, default="0.0.0.0", help="Host address to bind to"
|
||||||
)
|
)
|
||||||
parser.add_argument("--port", type=int, default=8000, help="Port to listen on")
|
parser.add_argument("--port", type=int, default=9004, help="Port to listen on")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
uvicorn.run(app, host=args.host, port=args.port)
|
uvicorn.run(app, host=args.host, port=args.port)
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
/* retoor <retoor@molodetz.nl> */
|
/* retoor <retoor@molodetz.nl> */
|
||||||
/* Mobile-First Responsive Styles */
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--touch-target-min: 44px;
|
--touch-target-min: 44px;
|
||||||
@ -12,7 +11,6 @@
|
|||||||
--safe-area-inset-right: env(safe-area-inset-right, 0);
|
--safe-area-inset-right: env(safe-area-inset-right, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hamburger Button */
|
|
||||||
.hamburger-btn {
|
.hamburger-btn {
|
||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -55,7 +53,6 @@
|
|||||||
background-color: rgba(0, 51, 153, 0.1);
|
background-color: rgba(0, 51, 153, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sidebar Overlay */
|
|
||||||
.sidebar-overlay {
|
.sidebar-overlay {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -76,7 +73,6 @@
|
|||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pull to Refresh Indicator */
|
|
||||||
.pull-to-refresh-indicator {
|
.pull-to-refresh-indicator {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -115,10 +111,9 @@
|
|||||||
to { transform: rotate(360deg); }
|
to { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Context Menu */
|
|
||||||
.context-menu {
|
.context-menu {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
min-width: 180px;
|
min-width: 200px;
|
||||||
max-width: 280px;
|
max-width: 280px;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@ -141,7 +136,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 12px 16px;
|
padding: 14px 16px;
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
@ -161,8 +156,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.context-menu-icon {
|
.context-menu-icon {
|
||||||
width: 20px;
|
width: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.context-menu-separator {
|
.context-menu-separator {
|
||||||
@ -171,7 +167,27 @@
|
|||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mobile Base Styles (320px+) */
|
.mobile-more-btn {
|
||||||
|
display: none;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
min-width: 36px;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: var(--text-color-light);
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-more-btn:active {
|
||||||
|
background-color: rgba(0, 51, 153, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.hamburger-btn {
|
.hamburger-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -222,7 +238,7 @@
|
|||||||
.header-right .button {
|
.header-right .button {
|
||||||
min-width: var(--touch-target-min);
|
min-width: var(--touch-target-min);
|
||||||
min-height: var(--touch-target-min);
|
min-height: var(--touch-target-min);
|
||||||
padding: 8px 10px;
|
padding: 8px 12px;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,46 +315,74 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.logged-in .app-footer {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-footer {
|
.app-footer {
|
||||||
padding: 12px 16px;
|
padding: 8px 12px;
|
||||||
padding-bottom: calc(12px + var(--safe-area-inset-bottom));
|
padding-bottom: calc(8px + var(--safe-area-inset-bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-links {
|
.footer-links {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 2px 10px;
|
gap: 2px 8px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-links li a {
|
.footer-links li a {
|
||||||
font-size: 0.65rem;
|
font-size: 0.6rem;
|
||||||
min-height: 32px;
|
min-height: 28px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 4px 0;
|
padding: 2px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-text {
|
.footer-text {
|
||||||
font-size: 0.65rem;
|
font-size: 0.6rem;
|
||||||
margin-top: 8px;
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list-container {
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* File List Mobile */
|
|
||||||
.file-list-header {
|
.file-list-header {
|
||||||
padding: 12px;
|
padding: 8px 0;
|
||||||
flex-wrap: wrap;
|
flex-direction: column;
|
||||||
gap: 8px;
|
align-items: stretch;
|
||||||
|
gap: 12px;
|
||||||
|
border-bottom: none;
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-list-title {
|
.file-list-header .header-left {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list-title,
|
||||||
|
.file-list-header h2 {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-controls {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-controls label {
|
||||||
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-actions {
|
.file-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@ -346,93 +390,137 @@
|
|||||||
.file-actions .button {
|
.file-actions .button {
|
||||||
min-height: var(--touch-target-min);
|
min-height: var(--touch-target-min);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: calc(50% - 4px);
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
padding: 10px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-grid {
|
.file-grid {
|
||||||
grid-template-columns: 1fr;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
gap: 1px;
|
gap: 1px;
|
||||||
background-color: var(--border-color);
|
background-color: var(--border-color);
|
||||||
padding: 0;
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item {
|
.file-item {
|
||||||
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 56px;
|
min-height: 60px;
|
||||||
padding: 12px 16px;
|
padding: 10px 12px;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
gap: 12px;
|
gap: 10px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border: none;
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item-checkbox {
|
.file-item:first-child {
|
||||||
width: 24px;
|
border-radius: 8px 8px 0 0;
|
||||||
height: 24px;
|
|
||||||
min-width: 24px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item-checkbox::before {
|
.file-item:last-child {
|
||||||
content: '';
|
border-radius: 0 0 8px 8px;
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
width: var(--touch-target-min);
|
|
||||||
height: var(--touch-target-min);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item-icon {
|
.file-item:only-child {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item .select-item {
|
||||||
|
position: relative;
|
||||||
|
top: auto;
|
||||||
|
left: auto;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
min-width: 20px;
|
||||||
|
opacity: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
min-width: 40px;
|
||||||
|
font-size: 2rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item-info {
|
.file-item-info,
|
||||||
|
.file-item .file-name {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item-name {
|
.file-name {
|
||||||
font-size: 1rem;
|
font-size: 0.9rem;
|
||||||
|
font-weight: 500;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
margin: 0;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item-meta {
|
.file-size {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
color: var(--text-color-light);
|
color: var(--text-color-light);
|
||||||
|
margin: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
min-width: 50px;
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item-actions {
|
.file-actions-menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-more-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-item-actions .action-btn {
|
.batch-actions {
|
||||||
width: var(--touch-target-min);
|
display: flex;
|
||||||
height: var(--touch-target-min);
|
flex-wrap: wrap;
|
||||||
min-width: var(--touch-target-min);
|
gap: 6px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Breadcrumb Mobile */
|
.batch-actions .button,
|
||||||
.breadcrumb {
|
.batch-actions .button-small {
|
||||||
padding: 8px 12px;
|
min-height: 36px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-nav {
|
||||||
|
padding: 8px 0;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-item {
|
.breadcrumb-item {
|
||||||
min-height: var(--touch-target-min);
|
min-height: var(--touch-target-min);
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 8px;
|
padding: 0 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overlays & Modals Mobile */
|
|
||||||
.modal-overlay,
|
.modal-overlay,
|
||||||
.file-upload-overlay,
|
.file-upload-overlay,
|
||||||
.file-preview-overlay,
|
.file-preview-overlay,
|
||||||
@ -452,17 +540,18 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bottom Sheet Style Modal */
|
|
||||||
.bottom-sheet {
|
.bottom-sheet {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
max-height: 90vh;
|
max-height: 85vh;
|
||||||
border-radius: 16px 16px 0 0;
|
border-radius: 16px 16px 0 0;
|
||||||
padding-bottom: var(--safe-area-inset-bottom);
|
padding-bottom: var(--safe-area-inset-bottom);
|
||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
z-index: 1001;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-sheet.visible {
|
.bottom-sheet.visible {
|
||||||
@ -477,7 +566,52 @@
|
|||||||
margin: 8px auto 16px;
|
margin: 8px auto 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Login View Mobile */
|
.bottom-sheet-header {
|
||||||
|
padding: 16px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-sheet-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-sheet-content {
|
||||||
|
padding: 8px 0;
|
||||||
|
max-height: 60vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-sheet-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 14px 20px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-sheet-item:active {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-sheet-item.destructive {
|
||||||
|
color: #d32f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-sheet-icon {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
width: 28px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.login-container {
|
.login-container {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
padding-top: calc(16px + var(--safe-area-inset-top));
|
padding-top: calc(16px + var(--safe-area-inset-top));
|
||||||
@ -503,21 +637,24 @@
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Photo Gallery Mobile */
|
|
||||||
.gallery-grid {
|
.gallery-grid {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gallery-item {
|
.gallery-item,
|
||||||
|
.photo-item {
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Toast Mobile */
|
.photo-item img {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.toast-notification {
|
.toast-notification {
|
||||||
left: 16px;
|
left: 12px;
|
||||||
right: 16px;
|
right: 12px;
|
||||||
bottom: calc(16px + var(--safe-area-inset-bottom));
|
bottom: calc(12px + var(--safe-area-inset-bottom));
|
||||||
max-width: none;
|
max-width: none;
|
||||||
transform: translateY(100px);
|
transform: translateY(100px);
|
||||||
}
|
}
|
||||||
@ -526,9 +663,8 @@
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Billing Dashboard Mobile */
|
|
||||||
.billing-container {
|
.billing-container {
|
||||||
padding: 16px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.billing-cards {
|
.billing-cards {
|
||||||
@ -539,32 +675,19 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.invoice-table-container {
|
.invoice-table-container,
|
||||||
overflow-x: auto;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.invoice-table {
|
|
||||||
min-width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Admin Dashboard Mobile */
|
|
||||||
.admin-container {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-table-container {
|
.user-table-container {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invoice-table,
|
||||||
.user-table {
|
.user-table {
|
||||||
min-width: 600px;
|
min-width: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* User Settings Mobile */
|
|
||||||
.settings-container {
|
.settings-container {
|
||||||
padding: 16px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-section .button {
|
.settings-section .button {
|
||||||
@ -572,7 +695,6 @@
|
|||||||
min-height: var(--touch-target-comfortable);
|
min-height: var(--touch-target-comfortable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Share Modal Mobile - Bottom Sheet */
|
|
||||||
.share-modal {
|
.share-modal {
|
||||||
top: auto;
|
top: auto;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@ -603,7 +725,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cookie Consent Mobile */
|
|
||||||
.cookie-consent {
|
.cookie-consent {
|
||||||
left: 8px;
|
left: 8px;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
@ -620,21 +741,160 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: var(--touch-target-min);
|
min-height: var(--touch-target-min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.upload-modal-content,
|
||||||
|
.share-modal-content {
|
||||||
|
max-height: 90vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-dashboard-container {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 479px) {
|
||||||
|
.app-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right .button {
|
||||||
|
padding: 8px 10px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-actions .button {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-size {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
min-width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
min-width: 36px;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch-actions .button {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
padding: 5px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-nav {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links li a {
|
||||||
|
font-size: 0.55rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-text {
|
||||||
|
font-size: 0.55rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 359px) {
|
||||||
|
.app-header {
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-title {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-center {
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right .button {
|
||||||
|
padding: 6px 8px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
min-width: 38px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-main {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item {
|
||||||
|
padding: 8px;
|
||||||
|
gap: 8px;
|
||||||
|
min-height: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
min-width: 32px;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-size {
|
||||||
|
font-size: 0.65rem;
|
||||||
|
min-width: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-more-btn {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
min-width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-actions {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-actions .button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch-actions {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch-actions .button {
|
||||||
|
font-size: 0.65rem;
|
||||||
|
padding: 4px 6px;
|
||||||
|
min-height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-controls label {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mobile Landscape (480px+) */
|
|
||||||
@media (min-width: 480px) and (max-width: 767px) {
|
@media (min-width: 480px) and (max-width: 767px) {
|
||||||
.gallery-grid {
|
.gallery-grid {
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-actions .button {
|
.file-actions .button {
|
||||||
min-width: auto;
|
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tablet (768px+) */
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.hamburger-btn {
|
.hamburger-btn {
|
||||||
display: none;
|
display: none;
|
||||||
@ -651,7 +911,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file-grid {
|
.file-grid {
|
||||||
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||||
|
background-color: transparent;
|
||||||
|
gap: calc(var(--spacing-unit) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item {
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-actions-menu {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-more-btn {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gallery-grid {
|
.gallery-grid {
|
||||||
@ -659,7 +936,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Desktop (1024px+) */
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.file-grid {
|
.file-grid {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||||
@ -670,12 +946,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Touch-specific styles */
|
|
||||||
@media (hover: none) and (pointer: coarse) {
|
@media (hover: none) and (pointer: coarse) {
|
||||||
.button:hover,
|
.button:hover,
|
||||||
.nav-link:hover,
|
.nav-link:hover,
|
||||||
.file-item:hover {
|
.file-item:hover {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
|
box-shadow: none;
|
||||||
|
border-color: var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:active,
|
.button:active,
|
||||||
@ -692,7 +969,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark Mode Mobile Adjustments */
|
|
||||||
body.dark-mode .hamburger-btn span {
|
body.dark-mode .hamburger-btn span {
|
||||||
background-color: var(--text-color);
|
background-color: var(--text-color);
|
||||||
}
|
}
|
||||||
@ -706,12 +982,14 @@ body.dark-mode .button:active {
|
|||||||
background-color: rgba(255, 255, 255, 0.1);
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .context-menu {
|
body.dark-mode .context-menu,
|
||||||
|
body.dark-mode .bottom-sheet {
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
|
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .context-menu-item:active {
|
body.dark-mode .context-menu-item:active,
|
||||||
|
body.dark-mode .bottom-sheet-item:active {
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,5 +998,5 @@ body.dark-mode .pull-to-refresh-indicator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .file-item {
|
body.dark-mode .file-item {
|
||||||
background-color: var(--background-color);
|
background-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,7 +138,7 @@ export class FileList extends HTMLElement {
|
|||||||
|
|
||||||
renderFolder(folder) {
|
renderFolder(folder) {
|
||||||
const isSelected = this.selectedFolders.has(folder.id);
|
const isSelected = this.selectedFolders.has(folder.id);
|
||||||
const starIcon = folder.is_starred ? '★' : '☆'; // Filled star or empty star
|
const starIcon = folder.is_starred ? '★' : '☆';
|
||||||
const starAction = folder.is_starred ? 'unstar-folder' : 'star-folder';
|
const starAction = folder.is_starred ? 'unstar-folder' : 'star-folder';
|
||||||
return `
|
return `
|
||||||
<div class="file-item folder-item" data-folder-id="${folder.id}">
|
<div class="file-item folder-item" data-folder-id="${folder.id}">
|
||||||
@ -149,6 +149,7 @@ export class FileList extends HTMLElement {
|
|||||||
<button class="action-btn" data-action="delete-folder" data-id="${folder.id}">Delete</button>
|
<button class="action-btn" data-action="delete-folder" data-id="${folder.id}">Delete</button>
|
||||||
<button class="action-btn star-btn" data-action="${starAction}" data-id="${folder.id}">${starIcon}</button>
|
<button class="action-btn star-btn" data-action="${starAction}" data-id="${folder.id}">${starIcon}</button>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="mobile-more-btn" data-folder-id="${folder.id}" aria-label="More actions">⋮</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -157,7 +158,7 @@ export class FileList extends HTMLElement {
|
|||||||
const isSelected = this.selectedFiles.has(file.id);
|
const isSelected = this.selectedFiles.has(file.id);
|
||||||
const icon = this.getFileIcon(file.mime_type);
|
const icon = this.getFileIcon(file.mime_type);
|
||||||
const size = this.formatFileSize(file.size);
|
const size = this.formatFileSize(file.size);
|
||||||
const starIcon = file.is_starred ? '★' : '☆'; // Filled star or empty star
|
const starIcon = file.is_starred ? '★' : '☆';
|
||||||
const starAction = file.is_starred ? 'unstar-file' : 'star-file';
|
const starAction = file.is_starred ? 'unstar-file' : 'star-file';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
@ -173,6 +174,7 @@ export class FileList extends HTMLElement {
|
|||||||
<button class="action-btn" data-action="share" data-id="${file.id}">Share</button>
|
<button class="action-btn" data-action="share" data-id="${file.id}">Share</button>
|
||||||
<button class="action-btn star-btn" data-action="${starAction}" data-id="${file.id}">${starIcon}</button>
|
<button class="action-btn star-btn" data-action="${starAction}" data-id="${file.id}">${starIcon}</button>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="mobile-more-btn" data-file-id="${file.id}" aria-label="More actions">⋮</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -260,6 +262,26 @@ export class FileList extends HTMLElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target.classList.contains('mobile-more-btn')) {
|
||||||
|
e.stopPropagation();
|
||||||
|
const fileId = target.dataset.fileId;
|
||||||
|
const folderId = target.dataset.folderId;
|
||||||
|
const rect = target.getBoundingClientRect();
|
||||||
|
|
||||||
|
if (fileId) {
|
||||||
|
const file = this.files.find(f => f.id === parseInt(fileId));
|
||||||
|
if (file) {
|
||||||
|
this.showFileContextMenu(rect.left, rect.bottom, file);
|
||||||
|
}
|
||||||
|
} else if (folderId) {
|
||||||
|
const folder = this.folders.find(f => f.id === parseInt(folderId));
|
||||||
|
if (folder) {
|
||||||
|
this.showFolderContextMenu(rect.left, rect.bottom, folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (target.classList.contains('select-item')) {
|
if (target.classList.contains('select-item')) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -100,6 +100,7 @@ export class MyWebdavApp extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showLogin() {
|
showLogin() {
|
||||||
|
document.body.classList.remove('logged-in');
|
||||||
this.innerHTML = `
|
this.innerHTML = `
|
||||||
<div class="login-container">
|
<div class="login-container">
|
||||||
<login-view></login-view>
|
<login-view></login-view>
|
||||||
@ -126,6 +127,7 @@ export class MyWebdavApp extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
document.body.classList.add('logged-in');
|
||||||
this.innerHTML = `
|
this.innerHTML = `
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<header class="app-header">
|
<header class="app-header">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user