1/* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import router from '@ohos.router' 17import mediaLibrary from '@ohos.multimedia.mediaLibrary' 18import { Logger, FileManager, ThumbnailImage } from '@ohos/feature-file-manager' 19import FileDataSource from '../../data/FileDataSource' 20 21const SIZE_M: number = 1024 * 1024 22const ONE_SECOND: number = 1000 23 24@Preview 25@Component 26export struct FileList { 27 @State fileList: FileDataSource = new FileDataSource() 28 @State isNoFile: boolean = true 29 @State showDeleteButton: boolean = false 30 title: Resource = {} as Resource; 31 mediaType: mediaLibrary.MediaType = mediaLibrary.MediaType.FILE 32 itemClickFunction: (fileAsset: mediaLibrary.FileAsset) => void = () => {} 33 34 async aboutToAppear() { 35 let files = await FileManager.getFileAssets(getContext(), this.mediaType) 36 if (files == undefined) { 37 Logger.error('files undefined') 38 return 39 } 40 if (files.getCount() > 0) { 41 Logger.debug('show list') 42 this.isNoFile = false 43 } 44 for (let i = 0; i < files.getCount(); i++) { 45 let fileAsset: mediaLibrary.FileAsset = await files.getNextObject() 46 if (fileAsset == undefined) { 47 continue 48 } 49 Logger.debug('getFileAssetsByType success, fileAsset.displayName ' + i + ': ' + fileAsset.displayName + 50 ' data:' + fileAsset.dateAdded + ', ' + fileAsset.dateModified) 51 this.fileList.pushData(fileAsset) 52 } 53 } 54 55 @Styles imagePressedStyles() { 56 .backgroundColor($r('app.color.item_pressed')) 57 .borderRadius(10) 58 } 59 60 build() { 61 Column() { 62 Row() { 63 Image($r('app.media.back')) 64 .id('back') 65 .width(36) 66 .height(36) 67 .objectFit(ImageFit.Fill) 68 .alignSelf(ItemAlign.Start) 69 .responseRegion({ 70 x: 0, 71 y: 0, 72 width: 45, 73 height: 45 74 }) 75 .stateStyles({ 76 pressed: this.imagePressedStyles 77 }) 78 .onClick(() => { 79 router.back() 80 }) 81 82 Text(this.title) 83 .fontSize(24) 84 .margin({ left: 10 }) 85 .fontWeight(FontWeight.Bold) 86 .fontColor($r('app.color.black')) 87 88 Blank() 89 90 if (this.mediaType === mediaLibrary.MediaType.FILE) { 91 Image($r('app.media.add')) 92 .id('fileAdd') 93 .width(36) 94 .height(36) 95 .objectFit(ImageFit.Fill) 96 .alignSelf(ItemAlign.End) 97 .responseRegion({ 98 x: 0, 99 y: 0, 100 width: 45, 101 height: 45 102 }) 103 .stateStyles({ 104 pressed: this.imagePressedStyles 105 }) 106 .onClick(async () => { 107 let fileAsset: mediaLibrary.FileAsset = await FileManager.createTxtFileAsset(getContext(this)) 108 if (fileAsset == undefined) { 109 Logger.error("createTxtFileAsset undefined") 110 return 111 } 112 this.fileList.pushData(fileAsset) 113 this.isNoFile = false 114 }) 115 } 116 } 117 .width('100%') 118 .margin({ top: 10, bottom: 20 }) 119 120 if (this.isNoFile) { 121 Column() { 122 Image($r('app.media.no_file')) 123 .id('no_file') 124 .width(36) 125 .height(36) 126 .margin({ top: 50 }) 127 .objectFit(ImageFit.Fill) 128 129 Text($r('app.string.no_file')) 130 .fontSize(16) 131 .margin({ top: 10 }) 132 .fontWeight(FontWeight.Bold) 133 .fontColor($r('app.color.font_gray')) 134 } 135 .width('100%') 136 } else { 137 List() { 138 LazyForEach(this.fileList, (listItem: mediaLibrary.FileAsset) => { 139 ListItem() { 140 FileListItemComponent({ 141 itemFileList: $fileList, 142 fileListItem: listItem, 143 itemClickFunction: this.itemClickFunction, 144 itemId: listItem.id, 145 itemShowDeleteButton: $showDeleteButton, 146 itemIsNoFile: $isNoFile 147 }) 148 } 149 }, (listItem: mediaLibrary.FileAsset) => JSON.stringify(listItem.title)) 150 } 151 .height('100%') 152 .width('100%') 153 } 154 } 155 .height('100%') 156 .width('100%') 157 .backgroundColor($r('app.color.white')) 158 .padding(20) 159 } 160} 161 162@Component 163struct FileListItemComponent { 164 @Link itemFileList: FileDataSource 165 @Link itemShowDeleteButton: boolean 166 @Link itemIsNoFile: boolean 167 private fileListItem: mediaLibrary.FileAsset = {} as mediaLibrary.FileAsset; 168 private itemClickFunction: (fileAsset: mediaLibrary.FileAsset) => void = () => {} 169 private itemId: number = 0 170 171 @Styles itemPressedStyles() { 172 .backgroundColor($r('app.color.item_pressed')) 173 .borderRadius(10) 174 } 175 176 build() { 177 Column() { 178 Row() { 179 ThumbnailImage({ fileAsset: this.fileListItem }) 180 .width(40) 181 .height(40) 182 .margin({ left: 20 }) 183 184 Column() { 185 Text(this.fileListItem.title) 186 .maxLines(1) 187 .width('75%') 188 .textOverflow({overflow:TextOverflow.Ellipsis}) 189 .fontSize(16) 190 .fontColor($r('app.color.black')) 191 192 Text(new Date(this.fileListItem.dateAdded * ONE_SECOND).toLocaleDateString() + ' - ' + 193 Math.ceil(this.fileListItem.size / SIZE_M) + 'M') 194 .fontSize(12) 195 .margin({ top: 5 }) 196 .fontColor($r('app.color.font_gray')) 197 } 198 .margin({ left: 10 }) 199 .alignItems(HorizontalAlign.Start) 200 201 Blank() 202 203 if (this.itemShowDeleteButton) { 204 Image($r('app.media.delete')) 205 .id('fileListDelete') 206 .width(30) 207 .height(30) 208 .margin({ right: 20 }) 209 .objectFit(ImageFit.Fill) 210 .responseRegion({ 211 x: 0, 212 y: 0, 213 width: 50, 214 height: 50 215 }) 216 .stateStyles({ 217 pressed: this.itemPressedStyles 218 }) 219 .onClick(() => { 220 FileManager.deleteFileAsset(this.fileListItem) 221 this.itemFileList.deleteData(this.itemId) 222 this.itemShowDeleteButton = false 223 if (this.itemFileList.totalCount() === 0) { 224 this.itemIsNoFile = true 225 } 226 }) 227 } 228 } 229 .height(56) 230 .width('100%') 231 .margin({ top: 10 }) 232 } 233 .width('100%') 234 .stateStyles({ 235 pressed: this.itemPressedStyles 236 }) 237 .onClick(async () => { 238 this.itemClickFunction(this.fileListItem) 239 }) 240 .gesture(LongPressGesture({ repeat: true }) 241 .onAction((event?: GestureEvent) => { 242 this.itemShowDeleteButton = true 243 }) 244 ) 245 } 246}