Last active: a year ago
export const publicType = {
image: '图片',
audio: '音频',
video: '视频',
file: '文件',
model: '模型',
vh5: '虚拟主播',
h5: 'H5',
flat: '分片图',
} as const;
export type PublicTypeKey = keyof typeof publicType;
export type PublicTypes = (typeof publicType)[PublicTypeKey];
// (alias) type PublicTypes = "图片" | "音频" | "视频" | "文件" | "模型" | "虚拟主播" | "H5" | "分片图"
Last active: a year ago
async function downloadFile(url, filename = '.') {
const res = await fetch(url);
const fileSize = res.headers.get('content-length');
log('File size: ', fileSize);
if (fs.existsSync('downloads')) {
await rm('downloads', { recursive: true, force: true });
}
await mkdir('downloads');
const destination = path.resolve('./downloads', filename);
const fileStream = fs.createWriteStream(destination, { flags: 'wx' });
const progressBar = terminal.progressBar({
width: 80,
title: filename,
eta: true,
precent: true,
});
let totalBytes = 0;
Last active: a year ago
import { ReactComponent as EmptyIcon } from '@/projects/editor/assets/images/media-library/empty.svg';
import useScrollLoading from '@/projects/viewer/hooks/useScrollLoading';
import { useAppSelector } from '@/store';
import { floderList } from '@/utils/api/assets-manage';
import {
getMediaList,
getPublicFolder,
getPublicMediaList,
MediaListDatum,
PublicFolderData,
} from '@/utils/fetchers';
import { LoadingOutlined } from '@ant-design/icons';
import { useRequest } from 'ahooks';
import { Segmented } from 'antd';
import { SegmentedValue } from 'antd/lib/segmented';
import {
lazy,
Suspense,
useCallback,
useEffect,
Last active: a year ago
import { useEffect, useRef } from 'react';
/**
* 利用 IntersectionObserver 实现滚动加载新数据的 hooks
*
* @param intersectedCallback 对应 anchor 相交时执行的回调
* @param option 判断条件,任意字段为 truthy 时不执行回调
*
* option 的变化才会使得重新 observe target
*
* @usage
* ```ts
* const { ref } = useScrollLoading(
* () => {
* setPage((d) => {
* d.page++;
* });
* },
* {
* loading,
Last active: a year ago
/* eslint-disable react-hooks/exhaustive-deps */
import { useRef, useState as useUpdate, useEffect as useMounted } from 'react';
export type Getter<T> = () => T;
export type Setter<T> = (newValue: T | ((oldValue: T) => T)) => void;
export type UseState = <T>(value: T) => [Getter<T>, Setter<T>];
export type Subs = Set<Effect>;
export type Effect = {
// 用于执行 useEffect 回调函数
execute: () => void;
// 保存该 useEffect 依赖的 state 对应的 subs 集合
deps: Set<Subs>;
};
const effectStack: Effect[] = [];
const subscribe = (effect: Effect, subs: Subs) => {
// 建立订阅关系
subs.add(effect);
// 建立依赖关系
Last active: a year ago
import { getPhoneMsg, GetPhoneMsgDatum } from '@/utils/api/sale-comments';
import { useRequest } from 'ahooks';
import { lazy, Suspense, useEffect, useMemo, useRef, useState } from 'react';
import Scrollbars from 'react-custom-scrollbars-2';
import { useImmer } from 'use-immer';
import SaleCard from './SaleCard';
import * as S from './SaleList.styles';
type Props = {
phone: string;
};
const SaleDetail = lazy(() => import('./SaleDetail'));
const SaleList = ({ phone }: Props) => {
const [page, setPage] = useImmer({
phone,
pageCount: 24,
page: 1,
});
Last active: a year ago
LightGallery React component
import LightGallery from 'lightgallery/react';
import 'lightgallery/css/lightgallery.css';
import 'lightgallery/css/lg-zoom.css';
import 'lightgallery/css/lg-thumbnail.css';
import lgThumbnail from 'lightgallery/plugins/thumbnail';
import lgZoom from 'lightgallery/plugins/zoom';
import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
export interface LightBoxProps
extends React.DetailedHTMLProps<
React.HTMLAttributes<HTMLDivElement>,
HTMLDivElement
> {
speed?: number;
images: string[];
index?: number;
onAfterClose?: () => void;
onAfterInit?: (instance: LightGalleryInstance) => void;
}
export type ImpertiveHandler = {
Last active: a year ago
cloc --fullpath --not-match-d="(node_modules|App/ios|App/android|target|dist)" --not-match-f="(yarn\.lock|package\.json|package\-lock\.json)" .
Last active: a year ago
Custom error
use base64::DecodeError;
use serde::{Serialize, Serializer};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum VError {
#[error("Request error: {0}")]
RequestFaild(#[from] reqwest::Error),
#[error("Decode error: {0}")]
DecodeError(#[from] DecodeError),
}
// https://github.com/tauri-apps/tauri/discussions/3913
impl Serialize for VError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.to_string().as_ref())
Last active: 10 months ago
Rust tracing logger with write to file
use std::env;
use tracing_subscriber::{fmt, prelude::*, registry, EnvFilter};
pub fn init_logger() {
let formatting_layer = fmt::layer()
// .pretty()
.with_thread_ids(false)
.with_target(false)
.with_writer(std::io::stdout);
let env_layer = EnvFilter::try_from_env("RHEA_LOG").unwrap_or_else(|_| {
format!("{}=info,tower_http=info,axum=info", env!("CARGO_PKG_NAME")).into()
});
registry().with(env_layer).with(formatting_layer).init();
}
Last active: 10 months ago
Rust tracing logger with write to file
use crate::config::Config;
use anyhow::Result;
use tracing_appender::{non_blocking::WorkerGuard, rolling};
use tracing_error::ErrorLayer;
use tracing_subscriber::{
filter, fmt, prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, Registry,
};
pub fn logger_init(config: &Config) -> Result<WorkerGuard> {
let log_path = config.log_path.as_ref().expect("Can not read log path");
let formatting_layer = fmt::layer()
// .pretty()
.with_thread_ids(true)
.with_target(false)
.with_writer(std::io::stdout);
let file_appender = rolling::daily(log_path, "rus-list.log");
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
let file_layer = fmt::layer()
Last active: 10 months ago
Rust tracing logger with write to file
use tracing::level_filters::LevelFilter;
use tracing_subscriber::{fmt, layer::SubscriberExt, registry, util::SubscriberInitExt, EnvFilter};
pub fn init_logger() {
let formatting_layer = fmt::layer()
.with_thread_ids(true)
.with_target(true)
.with_writer(std::io::stdout);
let env_layer = EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.with_env_var("SPIO_LOG")
.from_env_lossy();
registry().with(env_layer).with(formatting_layer).init();
}