@@ -8,11 +8,77 @@ import type { RenamingStore } from '../types'
88import axios , { isAxiosError } from '@nextcloud/axios'
99import { emit , subscribe } from '@nextcloud/event-bus'
1010import { NodeStatus } from '@nextcloud/files'
11+ import { DialogBuilder } from '@nextcloud/dialogs'
1112import { t } from '@nextcloud/l10n'
12- import { basename , dirname } from 'path'
13+ import { basename , dirname , extname } from 'path'
1314import { defineStore } from 'pinia'
1415import logger from '../logger'
1516import Vue from 'vue'
17+ import IconCancel from '@mdi/svg/svg/cancel.svg?raw'
18+ import IconCheck from '@mdi/svg/svg/check.svg?raw'
19+
20+ let isDialogVisible = false
21+
22+ const showWarningDialog = ( oldExtension : string , newExtension : string ) : Promise < boolean > => {
23+ if ( isDialogVisible ) {
24+ return Promise . resolve ( false )
25+ }
26+
27+ isDialogVisible = true
28+
29+ let message
30+
31+ if ( ! oldExtension && newExtension ) {
32+ message = t (
33+ 'files' ,
34+ 'Adding the file extension "{new}" may render the file unreadable.' ,
35+ { new : newExtension } ,
36+ )
37+ } else if ( ! newExtension ) {
38+ message = t (
39+ 'files' ,
40+ 'Removing the file extension "{old}" may render the file unreadable.' ,
41+ { old : oldExtension } ,
42+ )
43+ } else {
44+ message = t (
45+ 'files' ,
46+ 'Changing the file extension from "{old}" to "{new}" may render the file unreadable.' ,
47+ { old : oldExtension , new : newExtension } ,
48+ )
49+ }
50+
51+ return new Promise ( ( resolve ) => {
52+ const dialog = new DialogBuilder ( )
53+ . setName ( t ( 'files' , 'Change file extension' ) )
54+ . setText ( message )
55+ . setButtons ( [
56+ {
57+ label : t ( 'files' , 'Keep {oldextension}' , { oldextension : oldExtension } ) ,
58+ icon : IconCancel ,
59+ type : 'secondary' ,
60+ callback : ( ) => {
61+ isDialogVisible = false
62+ resolve ( false )
63+ } ,
64+ } ,
65+ {
66+ label : newExtension . length ? t ( 'files' , 'Use {newextension}' , { newextension : newExtension } ) : t ( 'files' , 'Remove extension' ) ,
67+ icon : IconCheck ,
68+ type : 'primary' ,
69+ callback : ( ) => {
70+ isDialogVisible = false
71+ resolve ( true )
72+ } ,
73+ } ,
74+ ] )
75+ . build ( )
76+
77+ dialog . show ( ) . then ( ( ) => {
78+ dialog . hide ( )
79+ } )
80+ } )
81+ }
1682
1783export const useRenamingStore = function ( ...args ) {
1884 const store = defineStore ( 'renaming' , {
@@ -36,6 +102,17 @@ export const useRenamingStore = function(...args) {
36102 const newName = this . newName . trim ?.( ) || ''
37103 const oldName = this . renamingNode . basename
38104 const oldEncodedSource = this . renamingNode . encodedSource
105+
106+ // Check for extension change
107+ const oldExtension = extname ( oldName )
108+ const newExtension = extname ( newName )
109+ if ( oldExtension !== newExtension ) {
110+ const proceed = await showWarningDialog ( oldExtension , newExtension )
111+ if ( ! proceed ) {
112+ return false
113+ }
114+ }
115+
39116 if ( oldName === newName ) {
40117 return false
41118 }
0 commit comments