Skip to content

feat: Frontend File Management and UI Enhancements#649

Open
Viyyy wants to merge 14 commits into
m1k1o:masterfrom
Viyyy:master
Open

feat: Frontend File Management and UI Enhancements#649
Viyyy wants to merge 14 commits into
m1k1o:masterfrom
Viyyy:master

Conversation

@Viyyy
Copy link
Copy Markdown

@Viyyy Viyyy commented May 22, 2026

New Features and Improvements

  1. Chrome Permissions: Lifted download restrictions and enabled clipboard access.
  2. File Management API: Added support for file renaming and deletion, improving management flexibility.
  3. File Panel Upgrades: Added type-based filtering and support for previewing images, videos, audio, PDFs, and text files.
  4. Clipboard Enhancements: Ctrl+V pasting of images/files automatically uploads to the container’s download directory, with filenames including type prefixes and timestamps.
  5. UI and Resolution Enhancements:
  6. Resolution menu supports custom width, height, and frame rate input.
  7. Added “Fit to Current Window Size” option.
  8. Fullscreen mode hides header/control/sidebar, with collapsible control bar.
  9. Settings persist in localStorage.

Impact

  1. Improves file operation efficiency and user experience.
  2. Allows smoother browser-based file management and clipboard operations for both developers and users.
  3. UI adapts to various resolutions for better display and interaction.
162ad2dcb2dd9e48de3085b4c98195ee

Copilot AI review requested due to automatic review settings May 22, 2026 08:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds richer file-management and clipboard-driven upload capabilities, plus several UI enhancements (resolution controls and a “web fullscreen” layout mode) to improve day-to-day remote desktop usage.

Changes:

  • Added file deletion/rename support in the filetransfer plugin and exposed them via legacy HTTP proxy endpoints.
  • Implemented frontend file filtering + preview modal, and added paste/drag-and-drop upload flows.
  • Updated Chrome container policies and UI layout to better support downloads, clipboard, and fullscreen-like behavior.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 18 comments.

Show a summary per file
File Description
server/internal/plugins/filetransfer/manager.go Adds DELETE/PATCH handlers for file deletion and rename.
server/internal/http/legacy/handler.go Proxies new clipboard/upload-drop + file delete/rename endpoints to the v3 API.
server/internal/api/room/handler.go Enables POST for clipboard image endpoint.
server/internal/api/room/clipboard.go Re-enables clipboard image upload support and adjusts imports/commented code.
Dockerfile.dev Adds a dev Dockerfile that builds server + client into a chrome runtime image.
docker-compose.yaml Switches compose to a dev chrome image and enables filetransfer + higher FPS/bitrate.
config.yml Enables upload-drop/file chooser dialog and changes implicit hosting default.
client/src/store/video.ts Persists screen resolution settings to localStorage.
client/src/store/client.ts Adds webFullscreen state + mutation.
client/src/neko/index.ts Restores persisted resolution for admins on connect.
client/src/neko/base.ts Prevents sending data over a non-open RTC data channel.
client/src/locale/zh-cn.ts Adds file-management UI strings (but missing transfers).
client/src/locale/en-us.ts Adds file-management UI strings including transfers.
client/src/components/video.vue Adds paste + drag/drop handlers and a web-fullscreen toggle.
client/src/components/resolution.vue Adds “fit to window” and custom resolution inputs.
client/src/components/files.vue Adds filtering, preview modal, rename/delete actions, and collapsible transfers area.
client/src/app.vue Hides header/sidebar/controls in web fullscreen and adds collapsible controls.
apps/google-chrome/supervisord.conf Removes --disable-file-system flag.
apps/google-chrome/policies.json Relaxes download restrictions and enables clipboard + file dialogs (broadly).
.gitignore Ignores data/**.
.claude/skills/dev-guide/SKILL.md Adds an internal development guide document.
.claude/settings.local.json Adds local tool-permissions configuration (new file).
Comments suppressed due to low confidence (3)

server/internal/http/legacy/handler.go:437

  • The backend response body returned from s.req is an io.ReadCloser and is not closed here. Add a defer body.Close() after successful s.req to avoid leaking HTTP connections/resources on repeated drop uploads.
		body, _, err := s.req(http.MethodPost, "/api/room/upload/drop", r.Header, r.Body)
		if err != nil {
			return utils.HttpInternalServerError().WithInternalErr(err)
		}

		_, err = io.Copy(w, body)
		return err
	})

server/internal/http/legacy/handler.go:489

  • This handler proxies the backend response but doesn’t close the io.ReadCloser from s.req and doesn’t copy Content-Type from backend headers. Consider deferring body.Close() and forwarding Content-Type so clients receive the correct MIME type for JSON responses.
		body, _, err := s.req(http.MethodPatch, "/api/filetransfer?filename="+url.QueryEscape(filename), r.Header, r.Body)
		if err != nil {
			return utils.HttpInternalServerError().WithInternalErr(err)
		}

		_, err = io.Copy(w, body)
		return err
	})

client/src/components/files.vue:553

  • download() creates an object URL for the downloaded blob but never revokes it. Consider revoking the URL after triggering the download to avoid accumulating blob URLs in long sessions.
        const a = document.createElement('a')
        a.href = URL.createObjectURL(new Blob([res.data]))
        a.setAttribute('download', item.name)
        document.body.appendChild(a); a.click(); document.body.removeChild(a)
        transfer.progress = transfer.size; transfer.status = 'completed'
      }).catch((error) => {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +366 to +370
if err := os.Remove(filePath); err != nil {
return utils.HttpInternalServerError().
WithInternalErr(err).
Msg("error deleting file")
}
Comment on lines +422 to +429
oldPath := filepath.Join(m.config.RootDir, filename)
newPath := filepath.Join(m.config.RootDir, newName)

if err := os.Rename(oldPath, newPath); err != nil {
return utils.HttpInternalServerError().
WithInternalErr(err).
Msg("error renaming file")
}
Comment on lines +406 to +412
body, _, err := s.req(http.MethodPost, "/api/room/clipboard/image.png", r.Header, r.Body)
if err != nil {
return utils.HttpInternalServerError().WithInternalErr(err)
}

_, err = io.Copy(w, body)
return err
Comment on lines +456 to +463
body, _, err := s.req(http.MethodDelete, "/api/filetransfer?filename="+url.QueryEscape(filename), r.Header, nil)
if err != nil {
return utils.HttpInternalServerError().WithInternalErr(err)
}

_, err = io.Copy(w, body)
return err
})
Comment on lines 123 to 133
export const files = {
downloads: '下载',
uploads: '上传',
upload_here: '点击或拖动文件到此处上传',
download: '下载',
rename: '重命名',
delete: '删除',
preview: '预览',
no_files: '暂无文件',
preview_unsupported: '该文件类型不支持预览',
}
Comment thread docker-compose.yaml Outdated
- NEKO_MEMBER_MULTIUSER_ADMIN_PASSWORD=admin
- NEKO_WEBRTC_EPR=52000-52100
- NEKO_WEBRTC_ICELITE=1
- NEKO_NAT1TO1=192.168.110.51
Comment on lines +22 to 26
"ClipboardAllowedForUrls": ["*"],
"URLAllowlist": [
"file:///home/neko/Downloads"
],
"URLBlocklist": [
--disable-file-system
--disable-gpu
--disable-software-rasterizer
--disable-dev-shm-usage
Comment on lines +3 to +17
"allow": [
"Skill(update-config)",
"Skill(update-config:*)",
"WebSearch",
"Bash(docker pull *)",
"Bash(docker build *)",
"Bash(docker run *)",
"Bash(docker rm *)",
"Bash(curl -s http://localhost:8080/api/stats)",
"Bash(docker exec *)",
"Bash(ipconfig)",
"Bash(docker compose *)",
"Bash(git add *)",
"Bash(git commit *)"
]
Comment thread config.yml
Comment on lines 22 to 25
session:
merciful_reconnect: true
# default setting for legacy API
implicit_hosting: false
implicit_hosting: true
cookie:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants