新增: 目录列表增加相册展示功能(大概时间、大概地点) (#62)

* 新增: 目录列表增加相册展示功能(大概时间、大概地点)

* fix:修复合并遗留bug

* update SubActions.js
This commit is contained in:
chauncey 2021-03-11 14:46:41 +08:00 committed by GitHub
parent ff0e2627dc
commit 29b8684976
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 3050 additions and 2740 deletions

View File

@ -52,7 +52,8 @@
"material-ui-toggle-icon": "^1.1.1",
"mdi-material-ui": "^6.9.0",
"mini-css-extract-plugin": "0.8.0",
"monaco-editor-webpack-plugin": "^1.9.0",
"monaco-editor": "0.19.0",
"monaco-editor-webpack-plugin": "1.8.0",
"optimize-css-assets-webpack-plugin": "5.0.3",
"pnp-webpack-plugin": "1.5.0",
"postcss-flexbugs-fixes": "4.1.0",

View File

@ -0,0 +1,36 @@
import React from "react";
import {makeStyles} from "@material-ui/core";
const useStyles = makeStyles(() => ({
container: {
padding: "7px"
},
fixFlex: {
minWidth: 0
},
dragging: {
opacity: 0.4
},
dateSubTitle: {
fontSize:"16px",
padding:"16px 0 16px 6px"
},
dateSubTitleDate: {
color:'#000'
},
dateSubTitleLocation: {
color:"#6b6b6b"
}
}));
export default function AlbumSubTitle(props) {
const dateText = props.date;
const locationText = props.location
const classes = useStyles();
return (
<div className={classes.dateSubTitle} >
<div className={classes.dateSubTitleDate}>{dateText} <small className={classes.dateSubTitleLocation}>{locationText}</small></div>
</div>
);
}

View File

@ -15,23 +15,18 @@ import SadIcon from "@material-ui/icons/SentimentVeryDissatisfied";
import EmptyIcon from "@material-ui/icons/Unarchive";
import classNames from "classnames";
import PropTypes from "prop-types";
import React, { Component } from "react";
import { configure, GlobalHotKeys } from "react-hotkeys";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import {
changeContextMenu,
navigateTo,
navigateUp,
openRemoveDialog,
setSelectedTarget
} from "../../actions/index";
import React, {Component} from "react";
import {configure, GlobalHotKeys} from "react-hotkeys";
import {connect} from "react-redux";
import {withRouter} from "react-router-dom";
import {changeContextMenu, navigateTo, navigateUp, openRemoveDialog, setSelectedTarget} from "../../actions/index";
import explorer from "../../redux/explorer";
import { isMac } from "../../utils";
import {isMac} from "../../utils";
import pathHelper from "../../utils/page";
import ContextMenu from "./ContextMenu";
import ImgPreivew from "./ImgPreview";
import ObjectIcon from "./ObjectIcon";
import PhotosAlbum from "./PhotosAlbum";
const styles = theme => ({
paper: {
@ -130,6 +125,10 @@ const styles = theme => ({
position: "absolute",
top: 20,
width: 1
},
photosGroupSection: {
display: "flex",
flexWrap: "wrap",
}
});
@ -354,6 +353,57 @@ class ExplorerCompoment extends Component {
</Table>
);
const photoAlbumView = (
<div className={classes.flexFix}>
{this.props.dirList.length !== 0 && (
<>
<Typography
data-clickAway={"true"}
variant="body2"
className={classes.typeHeader}
>
文件夹
</Typography>
<Grid
data-clickAway={"true"}
container
spacing={0}
alignItems="flex-start"
>
{this.props.dirList.map((value, index) => (
<Grid
key={value.id}
item
xs={6}
md={3}
sm={4}
lg={2}
>
<ObjectIcon
key={value.id}
file={value}
index={index}
/>
</Grid>
))}
</Grid>
</>
)}
{this.props.fileList.length !== 0 && (
<>
<Typography
data-clickAway={"true"}
variant="body2"
className={classes.typeHeader}
>
照片
</Typography>
<PhotosAlbum fileList={this.props.fileList}></PhotosAlbum>
</>
)}
</div>
);
const normalView = (
<div className={classes.flexFix}>
{this.props.dirList.length !== 0 && (
@ -400,11 +450,13 @@ class ExplorerCompoment extends Component {
文件
</Typography>
<Grid
data-clickAway={"true"}
container
spacing={0}
alignItems="flex-start"
data-clickAway={"true"}
container
spacing={0}
alignItems="flex-start"
className={classes.photosGroupSection}
>
{this.props.fileList.map((value, index) => (
<Grid
key={value.id}
@ -415,9 +467,9 @@ class ExplorerCompoment extends Component {
lg={2}
>
<ObjectIcon
key={value.id}
index={index}
file={value}
key={value.id}
index={index}
file={value}
/>
</Grid>
))}
@ -426,7 +478,7 @@ class ExplorerCompoment extends Component {
)}
</div>
);
const view = this.props.viewMethod === "list" ? listView : normalView;
const view = this.props.viewMethod === "list" ? listView : this.props.viewMethod == "photoAlbum" ? photoAlbumView : normalView;
return (
<div
onContextMenu={this.contextMenu}

View File

@ -9,12 +9,12 @@ import {
import { lighten } from "@material-ui/core/styles";
import classNames from "classnames";
import PropTypes from "prop-types";
import React, { Component } from "react";
import React, {Component} from "react";
import ContentLoader from "react-content-loader";
import { LazyLoadImage } from "react-lazy-load-image-component";
import { connect } from "react-redux";
import { withRouter } from "react-router";
import { baseURL } from "../../middleware/Api";
import {LazyLoadImage} from "react-lazy-load-image-component";
import {connect} from "react-redux";
import {withRouter} from "react-router";
import {baseURL} from "../../middleware/Api";
import pathHelper from "../../utils/page";
import TypeIcon from "./TypeIcon";
import CheckCircleRoundedIcon from "@material-ui/icons/CheckCircleRounded";
@ -35,6 +35,19 @@ const styles = theme => ({
theme.palette.type === "dark" ? 0.3 : 0.18
)
},
picSelected: {
"&:hover": {
border: "1px solid #d0d0d0"
},
// backgroundColor:
// theme.palette.type === "dark"
// ? "#fff"
// : lighten(theme.palette.primary.main, 0.8),
padding: "8px",
border: "solid 1px #d0d0d0",
backgroundColor: "#3f51b58f",
},
notSelected: {
"&:hover": {
@ -114,9 +127,22 @@ const styles = theme => ({
width: "100%"
},
shareFix: {
marginLeft: "20px"
marginLeft: "20px" },
hiddenTitle:{
display: "none"
},
checkIcon: {
resetPicParentContainer:{
borderRadius: 0,
height: "auto"
},
resetPicStyle: {
position: "absolute",
top:"0px",
left:"0px",
width:"100%",
verticalAlign: "bottom"
},
checkIcon: {
color: theme.palette.primary.main
}
});
@ -153,14 +179,26 @@ class FileIconCompoment extends Component {
);
const isMobile = statusHelper.isMobile();
const isPhotos = this.props.file.pic !== "" &&
!this.state.showPicIcon &&
this.props.file.pic !== " " &&
this.props.file.pic !== "null,null";
const viewMethod = this.props.viewMethod;
const picArr = this.props.file.pic.split(',')
const picPaddingBottom = picArr.length == 2 ? parseInt(picArr[1]) / parseInt(picArr[0]) * 100 : 0;
const showPhotoAlbum = (viewMethod == "photoAlbum" && picPaddingBottom > 0) ? true : false;
return (
<div className={classes.container}>
<div
className={classNames({[classes.container]: !showPhotoAlbum})}
>
<ButtonBase
focusRipple
className={classNames(
{
[classes.selected]: isSelected,
[classes.notSelected]: !isSelected
[classes.selected]: !showPhotoAlbum && isSelected,
[classes.notSelected]:!showPhotoAlbum && !isSelected
},
classes.button
)}
@ -169,13 +207,22 @@ class FileIconCompoment extends Component {
!this.state.showPicIcon &&
this.props.file.pic !== " " &&
this.props.file.pic !== "null,null" && (
<div className={classes.preview}>
<div className={classNames(classes.preview,{[classes.resetPicParentContainer]: showPhotoAlbum})} >
{showPhotoAlbum && (
<i style={{display: "block", paddingBottom:picPaddingBottom+"%"}}></i>
)}
<LazyLoadImage
className={classNames({
[classes.hide]: this.state.loading,
[classes.picPreview]: !this.state
.loading
})}
},
{
[classes.picSelected]: isSelected,
[classes.notSelected]: !isSelected,
[classes.resetPicStyle]: showPhotoAlbum
}
)}
src={
baseURL +
(isSharePage
@ -234,7 +281,7 @@ class FileIconCompoment extends Component {
this.state.showPicIcon ||
this.props.file.pic === " " ||
this.props.file.pic === "null,null") && <Divider />}
<div className={classes.fileInfo}>
<div className={classNames(classes.fileInfo, {[classes.hiddenTitle]:showPhotoAlbum && isPhotos})}>
{!this.props.share && (
<div
onClick={this.props.onIconClick}

View File

@ -61,6 +61,8 @@ export default function SubActions({ isSmall, share, inherit }) {
? "list"
: viewMethod === "list"
? "smallIcon"
: viewMethod === "smallIcon"
? "photoAlbum"
: "icon";
Auth.SetPreference("view_method", newMethod);
OpenLoadingDialog(newMethod);
@ -100,6 +102,15 @@ export default function SubActions({ isSmall, share, inherit }) {
<ViewModuleIcon fontSize={isSmall ? "small" : "default"} />
</IconButton>
)}
{viewMethod === "photoAlbum" && (
<IconButton
title="相册模式"
className={classes.sideButton}
onClick={toggleViewMethod}
>
<ViewModuleIcon fontSize={isSmall ? "small" : "default"} />
</IconButton>
)}
<IconButton
title="排序方式"

View File

@ -35,6 +35,9 @@ const useStyles = makeStyles(() => ({
},
dragging: {
opacity: 0.4
},
clearPadding:{
padding: 0
}
}));
@ -220,13 +223,13 @@ export default function ObjectIcon(props) {
</>
);
}
return (
<div
ref={drag}
className={classNames({
[classes.container]: viewMethod !== "list",
[classes.dragging]: isDragging
[classes.dragging]: isDragging,
[classes.clearPadding]: viewMethod === "photoAlbum" && props.file.type === "file"
})}
>
<div
@ -255,6 +258,9 @@ export default function ObjectIcon(props) {
file={props.file}
/>
)}
{props.file.type === "file" && viewMethod === "photoAlbum" && (
<FileIcon file={props.file} viewMethod={viewMethod}/>
)}
</div>
</div>
);

View File

@ -0,0 +1,119 @@
import React from "react";
import {Grid, makeStyles} from "@material-ui/core";
import AlbumSubTitle from "./AlbumSubTitle";
import ObjectIcon from "./ObjectIcon";
const useStyles = makeStyles(() => ({
container: {
padding: "7px"
},
fixFlex: {
minWidth: 0
},
dragging: {
opacity: 0.4
},
dateSubTitle: {
fontSize:"16px",
padding:"16px 0 16px 6px"
},
dateSubTitleDate: {
color:'#000'
},
dateSubTitleLocation: {
color:"#6b6b6b"
},
fileContainer: {
marginBottom: "5px",
marginRight: "5px",
borderRadius: 0,
height: "auto",
position: "relative"
}
}));
export default function PhotosAlbum(props) {
const classes = useStyles()
const files = props.fileList
const fileGroups = {}
const dateOrder = []
let index = 0
files.map(file => {
const dateObj = new Date(file.exif_date_time !== "" ? file.exif_date_time : file.date)
const dateDay = dateObj.getFullYear() + "年" + (dateObj.getMonth() + 1) + "月" + dateObj.getDate()+"日"
if(!Object.prototype.hasOwnProperty.call(fileGroups, dateDay)){
let location = ""
if(file.exit_address !== ""){
try{
const exifAddress = JSON.parse(file.exit_address)
location = exifAddress.address
}catch (e){
console.log(e)
}
}
fileGroups[dateDay] = {
date:file.date,
location: location,
files:[]
}
dateOrder.push(dateDay)
}
file.index = index
file.flexWidth = 0
file.flexGrow = 0
file.height = 0
const picSize = file.pic.split(',')
if(picSize.length == 2){
file.flexWidth = parseInt(picSize[0])*200/parseInt(picSize[1])
file.flexGrow = parseInt(picSize[0])*200/parseInt(picSize[1])
}
fileGroups[dateDay].files.push(file)
if(file.exit_address !== "" && fileGroups[dateDay].location === ""){
try{
const exifAddress = JSON.parse(file.exit_address)
fileGroups[dateDay].location = exifAddress.address
}catch (e){
console.log(e)
}
}
index = index + 1
})
return (
<div>
{dateOrder.map((dateDay) => (
<>
<AlbumSubTitle date={dateDay} location={fileGroups[dateDay].location}></AlbumSubTitle>
<Grid
data-clickAway={"true"}
container
spacing={0}
alignItems="flex-start"
style={{display: "flex",flexWrap: "wrap"}}
className={classes.photosGroupSection}
>
{
fileGroups[dateDay].files.map((value) => (
<div
key={value.id}
className={classes.fileContainer}
style={{ width:value.flexWidth >0 ? value.flexWidth+"px":'auto',flexGrow:value.flexGrow}}
>
<ObjectIcon
key={value.id}
index={value.index}
file={value}
/>
</div>
))
}
<div style={{content: "",flexGrow: "999999999"}}></div>
</Grid>
</>
))}
</div>
);
}

5446
yarn.lock

File diff suppressed because it is too large Load Diff