Merge branch 'feat/tauri-move-fields' into feat/tauri-grid

# Conflicts:
#	frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/DatePickerPopup.tsx
#	frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellWrapper.tsx
#	frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCheckboxCell.tsx
#	frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx
#	frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCell.tsx
#	frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts
#	frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts
This commit is contained in:
ascarbek 2023-04-04 17:16:05 +06:00
commit ed977868cf
107 changed files with 1462 additions and 532 deletions

View File

@ -324,6 +324,7 @@ jobs:
with: with:
upload_url: ${{ needs.create-release.outputs.upload_url }} upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.LINUX_APP_RELEASE_PATH }}/${{ env.LINUX_PACKAGE_NAME }} asset_path: ${{ env.LINUX_APP_RELEASE_PATH }}/${{ env.LINUX_PACKAGE_NAME }}
asset_name: ${{ env.LINUX_PACKAGE_NAME }} asset_name: ${{ env.LINUX_PACKAGE_NAME }}
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
@ -352,3 +353,12 @@ jobs:
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/appflowy_client:${{ github.ref_name }} tags: ${{ secrets.DOCKER_HUB_USERNAME }}/appflowy_client:${{ github.ref_name }}
cache-from: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache cache-from: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache,mode=max cache-to: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/af_build_cache:buildcache,mode=max
notify-discord:
runs-on: ubuntu-latest
needs: [build-for-linux, build-for-windows, build-for-macOS]
steps:
- name: Notify Discord
run: |
curl -H "Content-Type: application/json" -d '{"username": "release@appflowy", "content": "🎉 AppFlowy ${{ github.ref_name }} is available. https://github.com/AppFlowy-IO/AppFlowy/releases/tag/'${{ github.ref_name }}'"}' "https://discord.com/api/webhooks/${{ secrets.DISCORD }}"
shell: bash

View File

@ -1,5 +1,12 @@
# Release Notes # Release Notes
## Version 0.1.2 - 03/28/2023
### Bug Fixes
- Fix: update calendar selected range.
- Fix: duplicate view.
## Version 0.1.1 - 03/21/2023 ## Version 0.1.1 - 03/21/2023
### New features ### New features

View File

@ -23,7 +23,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi" CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi" CARGO_MAKE_CRATE_NAME = "dart-ffi"
LIB_NAME = "dart_ffi" LIB_NAME = "dart_ffi"
CURRENT_APP_VERSION = "0.1.1" CURRENT_APP_VERSION = "0.1.2"
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite" FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
PRODUCT_NAME = "AppFlowy" PRODUCT_NAME = "AppFlowy"
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html # CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html

View File

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="16" height="16" rx="8" fill="#00BCF0"/>
<rect x="7.5" y="4" width="1" height="8" rx="0.5" fill="#131720"/>
<rect x="12" y="7.5" width="1" height="8" rx="0.5" transform="rotate(90 12 7.5)" fill="#131720"/>
</svg>

After

Width:  |  Height:  |  Size: 321 B

View File

@ -188,10 +188,10 @@
"exportDatabase": "Export database", "exportDatabase": "Export database",
"selectFiles": "Select the files that need to be export", "selectFiles": "Select the files that need to be export",
"createNewFolder": "Create a new folder", "createNewFolder": "Create a new folder",
"createNewFolderDesc": "Tell us where you want to store your data ...", "createNewFolderDesc": "Tell us where you want to store your data",
"open": "Open", "open": "Open",
"openFolder": "Open an existing folder", "openFolder": "Open an existing folder",
"openFolderDesc": "Read and write it to your existing AppFlowy folder ...", "openFolderDesc": "Read and write it to your existing AppFlowy folder",
"folderHintText": "folder name", "folderHintText": "folder name",
"location": "Creating a new folder", "location": "Creating a new folder",
"locationDesc": "Pick a name for your AppFlowy data folder", "locationDesc": "Pick a name for your AppFlowy data folder",
@ -366,6 +366,7 @@
"changeCover": "Change Cover", "changeCover": "Change Cover",
"colors": "Colors", "colors": "Colors",
"images": "Images", "images": "Images",
"clearAll": "Clear All",
"abstract": "Abstract", "abstract": "Abstract",
"addCover": "Add Cover", "addCover": "Add Cover",
"addLocalImage": "Add local image", "addLocalImage": "Add local image",
@ -383,7 +384,6 @@
"imageSavingFailed": "Image Saving Failed", "imageSavingFailed": "Image Saving Failed",
"addIcon": "Add Icon" "addIcon": "Add Icon"
} }
} }
}, },
"board": { "board": {

View File

@ -40,6 +40,13 @@
"markdown": "Markdown", "markdown": "Markdown",
"copyLink": "複製連結" "copyLink": "複製連結"
}, },
"moreAction": {
"small": "小",
"medium": "中",
"large": "大",
"fontSize": "字體大小",
"import": "匯入"
},
"disclosureAction": { "disclosureAction": {
"rename": "重新命名", "rename": "重新命名",
"delete": "刪除", "delete": "刪除",
@ -64,6 +71,7 @@
}, },
"dialogCreatePageNameHint": "頁面名稱", "dialogCreatePageNameHint": "頁面名稱",
"questionBubble": { "questionBubble": {
"shortcuts": "快捷鍵",
"whatsNew": "新功能", "whatsNew": "新功能",
"help": "幫助 & 支援", "help": "幫助 & 支援",
"debug": { "debug": {
@ -90,11 +98,21 @@
"inlineCode": "程式碼", "inlineCode": "程式碼",
"quote": "區塊引言", "quote": "區塊引言",
"header": "標題", "header": "標題",
"highlight": "反白" "highlight": "反白",
"color": "顏色"
}, },
"tooltip": { "tooltip": {
"lightMode": "切換至亮色模式", "lightMode": "切換至亮色模式",
"darkMode": "切換至暗色模式" "darkMode": "切換至暗色模式",
"openAsPage": "以頁面開啓",
"addNewRow": "新增列表",
"openMenu": "點擊開啓選單",
"viewDataBase": "查看資料庫",
"referencePage": "這個 {name} 已參照"
},
"sideBar": {
"closeSidebar": "關閉側邊欄",
"openSidebar": "開啓側邊欄"
}, },
"notifications": { "notifications": {
"export": { "export": {
@ -114,7 +132,14 @@
"signIn": "登入", "signIn": "登入",
"signOut": "登出", "signOut": "登出",
"complete": "完成", "complete": "完成",
"save": "儲存" "save": "儲存",
"generate": "產生",
"esc": "離開",
"keep": "保存",
"tryAgain": "再試一次",
"discard": "放棄變更",
"replace": "取代",
"insertBelow": "在下面插入"
}, },
"label": { "label": {
"welcome": "歡迎!", "welcome": "歡迎!",
@ -142,22 +167,99 @@
"appearance": "外觀", "appearance": "外觀",
"language": "語言", "language": "語言",
"user": "使用者", "user": "使用者",
"files": "檔案",
"open": "開啟設定" "open": "開啟設定"
}, },
"appearance": { "appearance": {
"themeMode": { "themeMode": {
"label": "Theme Mode", "label": "主題模式",
"light": "亮色模式", "light": "亮色模式",
"dark": "暗色模式", "dark": "暗色模式",
"system": "Adapt to System" "system": "系統設定"
} },
"theme": "主題"
},
"files": {
"defaultLocation": "Appflowy 資料儲存位置",
"doubleTapToCopy": "雙擊以複製路徑",
"restoreLocation": "回復 Appflowy 預設路徑",
"customizeLocation": "開啓其他資料夾",
"restartApp": "請重新啓動以讓更動生效",
"exportDatabase": "匯出資料庫",
"selectFiles": "選擇需要匯出的檔案",
"createNewFolder": "建立新檔案",
"createNewFolderDesc": "選擇你想儲存資料的位置",
"open": "打開",
"openFolder": "開啓一個已經存在的資料夾",
"openFolderDesc": "讀寫已存在的 AppFlowy 資料夾",
"folderHintText": "資料夾名稱",
"location": "建立新資料夾",
"locationDesc": "命名 Appflowy 資料夾",
"browser": "瀏覽",
"create": "建立",
"folderPath": "儲存資料夾的路徑",
"locationCannotBeEmpty": "路徑不能爲空",
"pathCopiedSnackbar": "檔案儲存空間的路徑已被複製到剪貼簿!"
},
"user": {
"name": "名稱",
"icon": "圖標",
"selectAnIcon": "選擇圖標",
"pleaseInputYourOpenAIKey": "請輸入你的 OpenAI 密鑰"
} }
}, },
"grid": { "grid": {
"settings": { "settings": {
"filter": "篩選", "filter": "篩選",
"sort": "排序",
"sortBy": "排序方式", "sortBy": "排序方式",
"Properties": "內容" "Properties": "內容",
"group": "群組",
"addFilter": "增加",
"deleteFilter": "刪除篩選器",
"filterBy": "以...篩選",
"typeAValue": "輸入一個值...",
"layout": "佈局"
},
"textFilter": {
"contains": "包含",
"doesNotContain": "不包含",
"endsWith": "以...結尾",
"startWith": "以...開頭",
"is": "是",
"isNot": "不是",
"isEmpty": "爲空",
"isNotEmpty": "不爲空",
"choicechipPrefix": {
"isNot": "不是",
"startWith": "以...開頭",
"endWith": "以...結尾",
"isEmpty": "爲空",
"isNotEmpty": "不爲空"
}
},
"checkboxFilter": {
"isChecked": "已核取",
"isUnchecked": "未核取",
"choicechipPrefix": {
"is": "是"
}
},
"checklistFilter": {
"isComplete": "已完成",
"isIncomplted": "未完成"
},
"singleSelectOptionFilter": {
"is": "是",
"isNot": "不是",
"isEmpty": "爲空",
"isNotEmpty": "不爲空"
},
"multiSelectOptionFilter": {
"contains": "包含",
"doesNotContain": "不包含",
"isEmpty": "爲空",
"isNotEmpty": "不爲空"
}, },
"field": { "field": {
"hide": "隱藏", "hide": "隱藏",
@ -172,6 +274,7 @@
"singleSelectFieldName": "單選", "singleSelectFieldName": "單選",
"multiSelectFieldName": "多選", "multiSelectFieldName": "多選",
"urlFieldName": "網址", "urlFieldName": "網址",
"checklistFieldName": "核取列表",
"numberFormat": "數字格式", "numberFormat": "數字格式",
"dateFormat": "日期格式", "dateFormat": "日期格式",
"includeTime": "包含時間", "includeTime": "包含時間",
@ -186,13 +289,23 @@
"addSelectOption": "新增選項", "addSelectOption": "新增選項",
"optionTitle": "選項", "optionTitle": "選項",
"addOption": "新增選項", "addOption": "新增選項",
"editProperty": "編輯內容" "editProperty": "編輯內容",
"newColumn": "新欄位",
"deleteFieldPromptMessage": "你確定嗎?這個內容將被刪除"
},
"sort": {
"ascending": "升冪排序",
"descending": "降冪排序",
"deleteSort": "刪除排序",
"addSort": "新增排序"
}, },
"row": { "row": {
"duplicate": "複製", "duplicate": "複製",
"delete": "刪除", "delete": "刪除",
"textPlaceholder": "空", "textPlaceholder": "空",
"copyProperty": "已將內容複製至剪貼簿" "copyProperty": "已將內容複製至剪貼簿",
"count": "Count",
"newRow": "新列表"
}, },
"selectOption": { "selectOption": {
"create": "建立", "create": "建立",
@ -210,6 +323,9 @@
"panelTitle": "搜尋或建立選項", "panelTitle": "搜尋或建立選項",
"searchOption": "搜尋選項" "searchOption": "搜尋選項"
}, },
"checklist": {
"panelTitle": "新增物件"
},
"menuName": "網格" "menuName": "網格"
}, },
"document": { "document": {
@ -217,10 +333,78 @@
"date": { "date": {
"timeHintTextInTwelveHour": "01:00 PM", "timeHintTextInTwelveHour": "01:00 PM",
"timeHintTextInTwentyFourHour": "13:00" "timeHintTextInTwentyFourHour": "13:00"
},
"slashMenu": {
"board": {
"selectABoardToLinkTo": "選擇要連結的看板",
"createANewBoard": "建立新的看板"
},
"grid": {
"selectAGridToLinkTo": "選擇要連結的網格",
"createANewGrid": "建立新網格"
}
},
"plugins": {
"referencedBoard": "已參照的看板",
"referencedGrid": "已參照的網格",
"autoGeneratorMenuItemName": "OpenAI 寫手",
"autoGeneratorTitleName": "OpenAI: 叫人工智慧寫下任何事情...",
"autoGeneratorLearnMore": "Learn more",
"autoGeneratorGenerate": "產生",
"autoGeneratorHintText": "問 OpenAI ...",
"autoGeneratorCantGetOpenAIKey": "無法取得 OpenAI 密鑰",
"smartEdit": "人工智慧助理",
"openAI": "OpenAI",
"smartEditFixSpelling": "修正拼寫",
"warning": "⚠️ AI 的回答可能不精確或是存在誤導",
"smartEditSummarize": "總結",
"smartEditCouldNotFetchResult": "無法取得 OpenAI 的結果",
"smartEditCouldNotFetchKey": "無法取得 OpenAI 密鑰",
"smartEditDisabled": "在設定連結 OpenAI ",
"discardResponse": "你確定放棄人工智慧的回覆?",
"cover": {
"changeCover": "更換封面",
"colors": "顏色",
"images": "圖片",
"abstract": "摘要",
"addCover": "新增封面",
"addLocalImage": "新增本機圖片",
"invalidImageUrl": "無效的圖片網址",
"failedToAddImageToGallery": "新增圖片到圖庫失敗",
"enterImageUrl": "輸入圖片網址",
"add": "Add",
"back": "Back",
"saveToGallery": "儲存到",
"removeIcon": "移除圖標",
"pasteImageUrl": "複製圖片網址",
"or": "或",
"pickFromFiles": "挑選檔案",
"couldNotFetchImage": "無法截取圖片",
"imageSavingFailed": "圖片儲存失敗",
"addIcon": "新增圖標"
}
} }
}, },
"sideBar": { "board": {
"openSidebar": "Open sidebar", "column": {
"closeSidebar": "Close sidebar" "create_new_card": "建立"
},
"menuName": "看板"
},
"calendar": {
"menuName": "日曆",
"defaultNewCalendarTitle": "未命名的",
"navigation": {
"today": "今天",
"jumpToday": "跳至今天",
"previousMonth": "上個月",
"nextMonth": "下個月"
},
"settings": {
"showWeekNumbers": "顯示星期",
"showWeekends": "顯示週末",
"firstDayOfWeek": "一週的第一天",
"layoutDateField": "排列方式"
}
} }
} }

View File

@ -184,7 +184,7 @@ class _BoardContentState extends State<BoardContent> {
width: 20, width: 20,
child: svgWidget( child: svgWidget(
"home/add", "home/add",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
onAddButtonClick: () { onAddButtonClick: () {
@ -207,7 +207,7 @@ class _BoardContentState extends State<BoardContent> {
width: 20, width: 20,
child: svgWidget( child: svgWidget(
"home/add", "home/add",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
title: FlowyText.medium( title: FlowyText.medium(

View File

@ -113,7 +113,7 @@ class _SettingItem extends StatelessWidget {
}, },
leftIcon: svgWidget( leftIcon: svgWidget(
action.iconName(), action.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
); );

View File

@ -203,7 +203,7 @@ class _NewEventButton extends StatelessWidget {
iconPadding: EdgeInsets.zero, iconPadding: EdgeInsets.zero,
icon: svgWidget( icon: svgWidget(
"home/add", "home/add",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
width: 22, width: 22,
); );

View File

@ -43,7 +43,7 @@ class ChoiceChipButton extends StatelessWidget {
radius: const BorderRadius.all(Radius.circular(14)), radius: const BorderRadius.all(Radius.circular(14)),
leftIcon: svgWidget( leftIcon: svgWidget(
filterInfo.fieldInfo.fieldType.iconName(), filterInfo.fieldInfo.fieldType.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
rightIcon: _ChoicechipFilterDesc(filterDesc: filterDesc), rightIcon: _ChoicechipFilterDesc(filterDesc: filterDesc),
hoverColor: AFThemeExtension.of(context).lightGreyHover, hoverColor: AFThemeExtension.of(context).lightGreyHover,

View File

@ -162,7 +162,7 @@ class _FilterPropertyCell extends StatelessWidget {
onTap: () => onTap(fieldInfo), onTap: () => onTap(fieldInfo),
leftIcon: svgWidget( leftIcon: svgWidget(
fieldInfo.fieldType.iconName(), fieldInfo.fieldType.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }

View File

@ -34,7 +34,7 @@ class _DisclosureButtonState extends State<DisclosureButton> {
width: 20, width: 20,
icon: svgWidget( icon: svgWidget(
"editor/details", "editor/details",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
onPressed: () => controller.show(), onPressed: () => controller.show(),
); );

View File

@ -76,7 +76,7 @@ class _AddFilterButtonState extends State<AddFilterButton> {
hoverColor: AFThemeExtension.of(context).lightGreyHover, hoverColor: AFThemeExtension.of(context).lightGreyHover,
leftIcon: svgWidget( leftIcon: svgWidget(
"home/add", "home/add",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
onTap: () => popoverController.show(), onTap: () => popoverController.show(),
), ),

View File

@ -19,7 +19,7 @@ class GridAddRowButton extends StatelessWidget {
onTap: () => context.read<GridBloc>().add(const GridEvent.createRow()), onTap: () => context.read<GridBloc>().add(const GridEvent.createRow()),
leftIcon: svgWidget( leftIcon: svgWidget(
"home/add", "home/add",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }

View File

@ -168,7 +168,7 @@ class FieldCellButton extends StatelessWidget {
onTap: onTap, onTap: onTap,
leftIcon: svgWidget( leftIcon: svgWidget(
field.fieldType.iconName(), field.fieldType.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
radius: BorderRadius.zero, radius: BorderRadius.zero,
text: FlowyText.medium( text: FlowyText.medium(

View File

@ -61,7 +61,7 @@ class FieldTypeCell extends StatelessWidget {
onTap: () => onSelectField(fieldType), onTap: () => onSelectField(fieldType),
leftIcon: svgWidget( leftIcon: svgWidget(
fieldType.iconName(), fieldType.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
); );

View File

@ -116,11 +116,11 @@ class _SwitchFieldButton extends StatelessWidget {
margin: GridSize.typeOptionContentInsets, margin: GridSize.typeOptionContentInsets,
leftIcon: svgWidget( leftIcon: svgWidget(
bloc.state.field.fieldType.iconName(), bloc.state.field.fieldType.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
rightIcon: svgWidget( rightIcon: svgWidget(
"grid/more", "grid/more",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }

View File

@ -182,7 +182,7 @@ class CreateFieldButton extends StatelessWidget {
onTap: () {}, onTap: () {},
leftIcon: svgWidget( leftIcon: svgWidget(
"home/add", "home/add",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
popupBuilder: (BuildContext popover) { popupBuilder: (BuildContext popover) {

View File

@ -153,7 +153,7 @@ class DateFormatButton extends StatelessWidget {
onHover: onHover, onHover: onHover,
rightIcon: svgWidget( rightIcon: svgWidget(
"grid/more", "grid/more",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
); );
@ -184,7 +184,7 @@ class TimeFormatButton extends StatelessWidget {
onHover: onHover, onHover: onHover,
rightIcon: svgWidget( rightIcon: svgWidget(
"grid/more", "grid/more",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
); );

View File

@ -61,7 +61,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
margin: GridSize.typeOptionContentInsets, margin: GridSize.typeOptionContentInsets,
rightIcon: svgWidget( rightIcon: svgWidget(
"grid/more", "grid/more",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
text: Row( text: Row(
children: [ children: [

View File

@ -194,7 +194,7 @@ class _OptionCellState extends State<_OptionCell> {
padding: const EdgeInsets.symmetric(horizontal: 6.0), padding: const EdgeInsets.symmetric(horizontal: 6.0),
child: svgWidget( child: svgWidget(
"grid/details", "grid/details",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
], ],
@ -251,7 +251,7 @@ class _AddOptionButton extends StatelessWidget {
}, },
leftIcon: svgWidget( leftIcon: svgWidget(
"home/add", "home/add",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
), ),

View File

@ -106,7 +106,7 @@ class _DeleteTag extends StatelessWidget {
text: FlowyText.medium(LocaleKeys.grid_selectOption_deleteTag.tr()), text: FlowyText.medium(LocaleKeys.grid_selectOption_deleteTag.tr()),
leftIcon: svgWidget( leftIcon: svgWidget(
"grid/delete", "grid/delete",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
onTap: () { onTap: () {
context context

View File

@ -67,7 +67,7 @@ class _ActionCell extends StatelessWidget {
}, },
leftIcon: svgWidget( leftIcon: svgWidget(
action.iconName(), action.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
); );

View File

@ -161,7 +161,7 @@ class _SortPropertyCell extends StatelessWidget {
onTap: () => onTap(fieldInfo), onTap: () => onTap(fieldInfo),
leftIcon: svgWidget( leftIcon: svgWidget(
fieldInfo.fieldType.iconName(), fieldInfo.fieldType.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }

View File

@ -125,7 +125,7 @@ class _SortItem extends StatelessWidget {
hoverColor: AFThemeExtension.of(context).lightGreyHover, hoverColor: AFThemeExtension.of(context).lightGreyHover,
icon: svgWidget( icon: svgWidget(
"home/close", "home/close",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
@ -187,7 +187,7 @@ class _AddSortButtonState extends State<_AddSortButton> {
onTap: () => _popoverController.show(), onTap: () => _popoverController.show(),
leftIcon: svgWidget( leftIcon: svgWidget(
"home/add", "home/add",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
), ),
@ -222,7 +222,7 @@ class _DeleteSortButton extends StatelessWidget {
}, },
leftIcon: svgWidget( leftIcon: svgWidget(
"editor/delete", "editor/delete",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
); );

View File

@ -61,7 +61,7 @@ class SortChoiceChip extends StatelessWidget {
final text = LocaleKeys.grid_settings_sort.tr(); final text = LocaleKeys.grid_settings_sort.tr();
final leftIcon = svgWidget( final leftIcon = svgWidget(
"grid/setting/sort", "grid/setting/sort",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
); );
return SizedBox( return SizedBox(

View File

@ -82,7 +82,7 @@ class _GridGroupCell extends StatelessWidget {
text: FlowyText.medium(fieldInfo.name), text: FlowyText.medium(fieldInfo.name),
leftIcon: svgWidget( leftIcon: svgWidget(
fieldInfo.fieldType.iconName(), fieldInfo.fieldType.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
rightIcon: rightIcon, rightIcon: rightIcon,
onTap: () { onTap: () {

View File

@ -96,7 +96,7 @@ class _GridPropertyCellState extends State<_GridPropertyCell> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final checkmark = svgWidget( final checkmark = svgWidget(
widget.fieldInfo.visibility ? 'home/show' : 'home/hide', widget.fieldInfo.visibility ? 'home/show' : 'home/hide',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
); );
return SizedBox( return SizedBox(
@ -118,7 +118,7 @@ class _GridPropertyCellState extends State<_GridPropertyCell> {
text: FlowyText.medium(widget.fieldInfo.name), text: FlowyText.medium(widget.fieldInfo.name),
leftIcon: svgWidget( leftIcon: svgWidget(
widget.fieldInfo.fieldType.iconName(), widget.fieldInfo.fieldType.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
rightIcon: FlowyIconButton( rightIcon: FlowyIconButton(
hoverColor: Colors.transparent, hoverColor: Colors.transparent,

View File

@ -78,7 +78,7 @@ class _SettingItem extends StatelessWidget {
onTap: () => onAction(action), onTap: () => onAction(action),
leftIcon: svgWidget( leftIcon: svgWidget(
action.iconName(), action.iconName(),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
); );

View File

@ -232,7 +232,7 @@ class _CardMoreOption extends StatelessWidget with CardAccessory {
padding: const EdgeInsets.all(3.0), padding: const EdgeInsets.all(3.0),
child: svgWidget( child: svgWidget(
'grid/details', 'grid/details',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }
@ -254,7 +254,7 @@ class _CardEditOption extends StatelessWidget with CardAccessory {
padding: const EdgeInsets.all(3.0), padding: const EdgeInsets.all(3.0),
child: svgWidget( child: svgWidget(
'editor/edit', 'editor/edit',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }

View File

@ -3,11 +3,9 @@ import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flowy_infra/size.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:textstyle_extensions/textstyle_extensions.dart';
import '../cell_builder.dart'; import '../cell_builder.dart';
@ -69,7 +67,6 @@ class _PrimaryCellAccessoryState extends State<PrimaryCellAccessory>
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Tooltip( return Tooltip(
message: LocaleKeys.tooltip_openAsPage.tr(), message: LocaleKeys.tooltip_openAsPage.tr(),
textStyle: AFThemeExtension.of(context).caption.textColor(Colors.white),
child: svgWidget( child: svgWidget(
"grid/expander", "grid/expander",
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
@ -125,7 +122,6 @@ class _AccessoryHoverState extends State<AccessoryHover> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<Widget> children = [ List<Widget> children = [
const _Background(),
Padding(padding: widget.contentPadding, child: widget.child), Padding(padding: widget.contentPadding, child: widget.child),
]; ];
@ -173,28 +169,6 @@ class AccessoryHoverState extends ChangeNotifier {
bool get onHover => _onHover; bool get onHover => _onHover;
} }
class _Background extends StatelessWidget {
const _Background({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Consumer<AccessoryHoverState>(
builder: (context, state, child) {
if (state.onHover) {
return FlowyHoverContainer(
style: HoverStyle(
borderRadius: Corners.s6Border,
hoverColor: AFThemeExtension.of(context).lightGreyHover,
),
);
} else {
return const SizedBox();
}
},
);
}
}
class CellAccessoryContainer extends StatelessWidget { class CellAccessoryContainer extends StatelessWidget {
final List<GridCellAccessoryBuilder> accessories; final List<GridCellAccessoryBuilder> accessories;
const CellAccessoryContainer({required this.accessories, Key? key}) const CellAccessoryContainer({required this.accessories, Key? key})

View File

@ -137,7 +137,7 @@ class _ChecklistOptionCellState extends State<_ChecklistOptionCell> {
iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2), iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
icon: svgWidget( icon: svgWidget(
"editor/details", "editor/details",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }

View File

@ -173,13 +173,13 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> {
leftChevronPadding: EdgeInsets.zero, leftChevronPadding: EdgeInsets.zero,
leftChevronIcon: svgWidget( leftChevronIcon: svgWidget(
"home/arrow_left", "home/arrow_left",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
rightChevronPadding: EdgeInsets.zero, rightChevronPadding: EdgeInsets.zero,
rightChevronMargin: EdgeInsets.zero, rightChevronMargin: EdgeInsets.zero,
rightChevronIcon: svgWidget( rightChevronIcon: svgWidget(
"home/arrow_right", "home/arrow_right",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
headerMargin: const EdgeInsets.only(bottom: 8.0), headerMargin: const EdgeInsets.only(bottom: 8.0),
), ),
@ -254,7 +254,7 @@ class _IncludeTimeButton extends StatelessWidget {
children: [ children: [
svgWidget( svgWidget(
"grid/clock", "grid/clock",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
const HSpace(4), const HSpace(4),
FlowyText.medium(LocaleKeys.grid_field_includeTime.tr()), FlowyText.medium(LocaleKeys.grid_field_includeTime.tr()),
@ -387,7 +387,7 @@ class _DateTypeOptionButton extends StatelessWidget {
margin: GridSize.typeOptionContentInsets, margin: GridSize.typeOptionContentInsets,
rightIcon: svgWidget( rightIcon: svgWidget(
"grid/more", "grid/more",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
), ),

View File

@ -116,7 +116,7 @@ class SelectOptionTag extends StatelessWidget {
hoverColor: Colors.transparent, hoverColor: Colors.transparent,
icon: svgWidget( icon: svgWidget(
'home/close', 'home/close',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
], ],

View File

@ -277,7 +277,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
iconPadding: const EdgeInsets.symmetric(horizontal: 6.0), iconPadding: const EdgeInsets.symmetric(horizontal: 6.0),
icon: svgWidget( icon: svgWidget(
"editor/details", "editor/details",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
], ],

View File

@ -213,7 +213,7 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
offset: const Offset(0, 8), offset: const Offset(0, 8),
child: svgWidget( child: svgWidget(
"editor/edit", "editor/edit",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
popupBuilder: (BuildContext popoverContext) { popupBuilder: (BuildContext popoverContext) {
return URLEditorPopover( return URLEditorPopover(
@ -246,7 +246,7 @@ class _CopyURLAccessoryState extends State<_CopyURLAccessory>
Widget build(BuildContext context) { Widget build(BuildContext context) {
return svgWidget( return svgWidget(
"editor/copy", "editor/copy",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
); );
} }

View File

@ -103,7 +103,7 @@ class _CloseButton extends StatelessWidget {
iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2), iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
icon: svgWidget( icon: svgWidget(
"home/close", "home/close",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }

View File

@ -34,7 +34,8 @@ class DocumentBanner extends StatelessWidget {
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
bgColor: Colors.transparent, bgColor: Colors.transparent,
hoverColor: Theme.of(context).colorScheme.primary, hoverColor: Theme.of(context).colorScheme.primary,
downColor: Theme.of(context).colorScheme.primaryContainer, highlightColor:
Theme.of(context).colorScheme.primaryContainer,
outlineColor: Colors.white, outlineColor: Colors.white,
borderRadius: Corners.s8Border, borderRadius: Corners.s8Border,
onPressed: onRestore, onPressed: onRestore,
@ -50,7 +51,7 @@ class DocumentBanner extends StatelessWidget {
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
bgColor: Colors.transparent, bgColor: Colors.transparent,
hoverColor: Theme.of(context).colorScheme.primaryContainer, hoverColor: Theme.of(context).colorScheme.primaryContainer,
downColor: Theme.of(context).colorScheme.primary, highlightColor: Theme.of(context).colorScheme.primary,
outlineColor: Colors.white, outlineColor: Colors.white,
borderRadius: Corners.s8Border, borderRadius: Corners.s8Border,
onPressed: onDelete, onPressed: onDelete,

View File

@ -32,6 +32,7 @@ class _FontSizeSwitcherState extends State<FontSizeSwitcher> {
FlowyText.semibold( FlowyText.semibold(
LocaleKeys.moreAction_fontSize.tr(), LocaleKeys.moreAction_fontSize.tr(),
fontSize: 12, fontSize: 12,
color: Theme.of(context).colorScheme.tertiary,
), ),
const SizedBox( const SizedBox(
height: 5, height: 5,
@ -43,9 +44,8 @@ class _FontSizeSwitcherState extends State<FontSizeSwitcher> {
_updateSelectedFontSize(_fontSizes[index].item2); _updateSelectedFontSize(_fontSizes[index].item2);
}, },
borderRadius: const BorderRadius.all(Radius.circular(5)), borderRadius: const BorderRadius.all(Radius.circular(5)),
selectedBorderColor: Theme.of(context).colorScheme.primaryContainer, selectedColor: Theme.of(context).colorScheme.tertiary,
selectedColor: Theme.of(context).colorScheme.onSurface, fillColor: Theme.of(context).colorScheme.primary,
fillColor: Theme.of(context).colorScheme.primaryContainer,
color: Theme.of(context).hintColor, color: Theme.of(context).hintColor,
constraints: const BoxConstraints( constraints: const BoxConstraints(
minHeight: 40.0, minHeight: 40.0,

View File

@ -28,7 +28,7 @@ class DocumentMoreButton extends StatelessWidget {
child: svgWidget( child: svgWidget(
'editor/details', 'editor/details',
size: const Size(18, 18), size: const Size(18, 18),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
); );
} }

View File

@ -119,7 +119,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
iconPadding: const EdgeInsets.all(3), iconPadding: const EdgeInsets.all(3),
icon: svgWidget( icon: svgWidget(
'common/information', 'common/information',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
// Name // Name
@ -143,7 +143,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
iconPadding: const EdgeInsets.all(3), iconPadding: const EdgeInsets.all(3),
icon: svgWidget( icon: svgWidget(
'common/settings', 'common/settings',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
onPressed: () => controller.show(), onPressed: () => controller.show(),
); );

View File

@ -149,7 +149,7 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
FlowyButton( FlowyButton(
leftIcon: svgWidget( leftIcon: svgWidget(
_iconName(value), _iconName(value),
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
text: FlowyText.regular(value.name), text: FlowyText.regular(value.name),
onTap: () => widget.onSelected(app.value1, value), onTap: () => widget.onSelected(app.value1, value),

View File

@ -18,7 +18,7 @@ SelectionMenuItem boardMenuItem = SelectionMenuItem(
); );
}, },
// TODO(a-wallen): Translate keywords // TODO(a-wallen): Translate keywords
keywords: ['referenced board', 'referenced kanban'], keywords: ['referenced', 'board', 'kanban'],
handler: (editorState, menuService, context) { handler: (editorState, menuService, context) {
showLinkToPageMenu( showLinkToPageMenu(
editorState, editorState,

View File

@ -2,17 +2,20 @@ import 'dart:io';
import 'dart:ui'; import 'dart:ui';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/presentation/plugins/cover/change_cover_popover_bloc.dart';
import 'package:appflowy/plugins/document/presentation/plugins/cover/cover_image_picker.dart'; import 'package:appflowy/plugins/document/presentation/plugins/cover/cover_image_picker.dart';
import 'package:appflowy/plugins/document/presentation/plugins/cover/cover_node_widget.dart'; import 'package:appflowy/plugins/document/presentation/plugins/cover/cover_node_widget.dart';
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart'; import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
const String kLocalImagesKey = 'local_images'; const String kLocalImagesKey = 'local_images';
@ -71,31 +74,35 @@ class CoverColorPicker extends StatefulWidget {
} }
class _ChangeCoverPopoverState extends State<ChangeCoverPopover> { class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
late Future<List<String>>? fileImages;
bool isAddingImage = false; bool isAddingImage = false;
@override
void initState() {
super.initState();
fileImages = _getPreviouslyPickedImagePaths();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return BlocProvider(
padding: const EdgeInsets.all(15), create: (context) => ChangeCoverPopoverBloc()
child: SingleChildScrollView( ..add(const ChangeCoverPopoverEvent.fetchPickedImagePaths()),
child: isAddingImage child: BlocBuilder<ChangeCoverPopoverBloc, ChangeCoverPopoverState>(
? CoverImagePicker( builder: (context, state) {
onBackPressed: () => setState(() { return Padding(
isAddingImage = false; padding: const EdgeInsets.all(15),
}), child: SingleChildScrollView(
onFileSubmit: (List<String> path) { child: isAddingImage
setState(() { ? CoverImagePicker(
isAddingImage = false; onBackPressed: () => setState(() {
}); isAddingImage = false;
}) }),
: _buildCoverSelection(), onFileSubmit: (List<String> path) {
context.read<ChangeCoverPopoverBloc>().add(
const ChangeCoverPopoverEvent
.fetchPickedImagePaths());
setState(() {
isAddingImage = false;
});
})
: _buildCoverSelection(),
),
);
},
), ),
); );
} }
@ -104,21 +111,55 @@ class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
FlowyText.semibold(LocaleKeys.document_plugins_cover_colors.tr()), FlowyText.semibold(
LocaleKeys.document_plugins_cover_colors.tr(),
color: Theme.of(context).colorScheme.tertiary,
),
const SizedBox(height: 10), const SizedBox(height: 10),
_buildColorPickerList(), _buildColorPickerList(),
const SizedBox(height: 10), const SizedBox(height: 10),
FlowyText.semibold(LocaleKeys.document_plugins_cover_images.tr()), _buildImageHeader(),
const SizedBox(height: 10), const SizedBox(height: 10),
_buildFileImagePicker(), _buildFileImagePicker(),
const SizedBox(height: 10), const SizedBox(height: 10),
FlowyText.semibold(LocaleKeys.document_plugins_cover_abstract.tr()), FlowyText.semibold(
LocaleKeys.document_plugins_cover_abstract.tr(),
color: Theme.of(context).colorScheme.tertiary,
),
const SizedBox(height: 10), const SizedBox(height: 10),
_buildAbstractImagePicker(), _buildAbstractImagePicker(),
], ],
); );
} }
Widget _buildImageHeader() {
return BlocBuilder<ChangeCoverPopoverBloc, ChangeCoverPopoverState>(
builder: (context, state) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FlowyText.semibold(
LocaleKeys.document_plugins_cover_images.tr(),
color: Theme.of(context).colorScheme.tertiary,
),
FlowyTextButton(
fillColor: Theme.of(context).cardColor,
hoverColor: Theme.of(context).colorScheme.secondaryContainer,
LocaleKeys.document_plugins_cover_clearAll.tr(),
fontColor: Theme.of(context).colorScheme.tertiary,
onPressed: () {
context
.read<ChangeCoverPopoverBloc>()
.add(const ChangeCoverPopoverEvent.clearAllImages());
},
mainAxisAlignment: MainAxisAlignment.end,
),
],
);
},
);
}
Widget _buildAbstractImagePicker() { Widget _buildAbstractImagePicker() {
return GridView.builder( return GridView.builder(
shrinkWrap: true, shrinkWrap: true,
@ -173,71 +214,59 @@ class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
} }
Widget _buildFileImagePicker() { Widget _buildFileImagePicker() {
return FutureBuilder<List<String>>( return BlocBuilder<ChangeCoverPopoverBloc, ChangeCoverPopoverState>(
future: _getPreviouslyPickedImagePaths(), builder: (context, state) {
builder: (context, snapshot) { if (state is Loaded) {
if (snapshot.hasData) { List<String> images = state.imageNames;
List<String> images = snapshot.data!; return GridView.builder(
return GridView.builder( shrinkWrap: true,
shrinkWrap: true, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3,
crossAxisCount: 3, childAspectRatio: 1 / 0.65,
childAspectRatio: 1 / 0.65, crossAxisSpacing: 7,
crossAxisSpacing: 7, mainAxisSpacing: 7,
mainAxisSpacing: 7, ),
), itemCount: images.length + 1,
itemCount: images.length + 1, itemBuilder: (BuildContext ctx, index) {
itemBuilder: (BuildContext ctx, index) { if (index == 0) {
if (index == 0) { return Container(
return Container( decoration: BoxDecoration(
decoration: BoxDecoration( color:
color: Theme.of(context) Theme.of(context).colorScheme.primary.withOpacity(0.15),
.colorScheme border: Border.all(
.primary color: Theme.of(context).colorScheme.primary,
.withOpacity(0.15),
border: Border.all(
color: Theme.of(context).colorScheme.primary,
),
borderRadius: Corners.s8Border,
),
child: FlowyIconButton(
iconPadding: EdgeInsets.zero,
icon: Icon(
Icons.add,
color: Theme.of(context).colorScheme.primary,
),
width: 20,
onPressed: () {
setState(() {
isAddingImage = true;
});
},
),
);
}
return InkWell(
onTap: () {
widget.onCoverChanged(
CoverSelectionType.file,
images[index - 1],
);
},
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: FileImage(File(images[index - 1])),
fit: BoxFit.cover,
),
borderRadius: Corners.s8Border,
),
), ),
borderRadius: Corners.s8Border,
),
child: FlowyIconButton(
iconPadding: EdgeInsets.zero,
icon: Icon(
Icons.add,
color: Theme.of(context).colorScheme.primary,
),
width: 20,
onPressed: () {
setState(() {
isAddingImage = true;
});
},
),
);
}
return ImageGridItem(
onImageSelect: () {
widget.onCoverChanged(
CoverSelectionType.file,
images[index - 1],
); );
}, },
imagePath: images[index - 1],
); );
} else { },
return Container(); );
} }
}); return Container();
});
} }
List<ColorOption> _generateBackgroundColorOptions(EditorState editorState) { List<ColorOption> _generateBackgroundColorOptions(EditorState editorState) {
@ -248,19 +277,75 @@ class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
)) ))
.toList(); .toList();
} }
}
Future<List<String>> _getPreviouslyPickedImagePaths() async { class ImageGridItem extends StatefulWidget {
SharedPreferences prefs = await SharedPreferences.getInstance(); const ImageGridItem({
final imageNames = prefs.getStringList(kLocalImagesKey) ?? []; Key? key,
final removeNames = []; required this.onImageSelect,
for (final name in imageNames) { required this.imagePath,
if (!File(name).existsSync()) { }) : super(key: key);
removeNames.add(name);
} final Function() onImageSelect;
} final String imagePath;
imageNames.removeWhere((element) => removeNames.contains(element));
prefs.setStringList(kLocalImagesKey, imageNames); @override
return imageNames; State<ImageGridItem> createState() => _ImageGridItemState();
}
class _ImageGridItemState extends State<ImageGridItem> {
bool showDeleteButton = false;
@override
Widget build(BuildContext context) {
return MouseRegion(
onEnter: (_) {
setState(() {
showDeleteButton = true;
});
},
onExit: (_) {
setState(() {
showDeleteButton = false;
});
},
child: Stack(
children: [
InkWell(
onTap: widget.onImageSelect,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: FileImage(File(widget.imagePath)),
fit: BoxFit.cover,
),
borderRadius: Corners.s8Border,
),
),
),
if (showDeleteButton)
Positioned(
right: 2,
top: 2,
child: FlowyIconButton(
fillColor:
Theme.of(context).colorScheme.surface.withOpacity(0.8),
hoverColor:
Theme.of(context).colorScheme.surface.withOpacity(0.8),
iconPadding: const EdgeInsets.all(5),
width: 28,
icon: svgWidget(
'editor/delete',
color: Theme.of(context).colorScheme.tertiary,
),
onPressed: () {
context.read<ChangeCoverPopoverBloc>().add(
ChangeCoverPopoverEvent.deleteImage(widget.imagePath));
},
),
),
],
),
);
} }
} }

View File

@ -0,0 +1,90 @@
import 'dart:async';
import 'dart:io';
import 'package:appflowy/plugins/document/presentation/plugins/cover/change_cover_popover.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:shared_preferences/shared_preferences.dart';
part 'change_cover_popover_bloc.freezed.dart';
class ChangeCoverPopoverBloc
extends Bloc<ChangeCoverPopoverEvent, ChangeCoverPopoverState> {
late final SharedPreferences _prefs;
final _initCompleter = Completer<void>();
ChangeCoverPopoverBloc() : super(const ChangeCoverPopoverState.initial()) {
SharedPreferences.getInstance().then((prefs) {
_prefs = prefs;
_initCompleter.complete();
});
on<ChangeCoverPopoverEvent>((event, emit) async {
await event.map(
fetchPickedImagePaths:
(FetchPickedImagePaths fetchPickedImagePaths) async {
final imageNames = await _getPreviouslyPickedImagePaths();
emit(ChangeCoverPopoverState.loaded(imageNames));
},
deleteImage: (DeleteImage deleteImage) async {
final currentState = state;
if (currentState is Loaded) {
await _deleteImageInStorage(deleteImage.path);
final updateImageList = currentState.imageNames
.where((path) => path != deleteImage.path)
.toList();
await _updateImagePathsInStorage(updateImageList);
emit(Loaded(updateImageList));
}
},
clearAllImages: (ClearAllImages clearAllImages) async {
final currentState = state;
if (currentState is Loaded) {
for (final image in currentState.imageNames) {
await _deleteImageInStorage(image);
}
await _updateImagePathsInStorage([]);
emit(const Loaded([]));
}
},
);
});
}
Future<List<String>> _getPreviouslyPickedImagePaths() async {
await _initCompleter.future;
final imageNames = _prefs.getStringList(kLocalImagesKey) ?? [];
if (imageNames.isEmpty) {
return imageNames;
}
imageNames.removeWhere((name) => !File(name).existsSync());
return imageNames;
}
Future<void> _updateImagePathsInStorage(List<String> imagePaths) async {
await _initCompleter.future;
_prefs.setStringList(kLocalImagesKey, imagePaths);
return;
}
Future<void> _deleteImageInStorage(String path) async {
final imageFile = File(path);
await imageFile.delete();
}
}
@freezed
class ChangeCoverPopoverEvent with _$ChangeCoverPopoverEvent {
const factory ChangeCoverPopoverEvent.fetchPickedImagePaths() =
FetchPickedImagePaths;
const factory ChangeCoverPopoverEvent.deleteImage(String path) = DeleteImage;
const factory ChangeCoverPopoverEvent.clearAllImages() = ClearAllImages;
}
@freezed
class ChangeCoverPopoverState with _$ChangeCoverPopoverState {
const factory ChangeCoverPopoverState.initial() = Initial;
const factory ChangeCoverPopoverState.loading() = Loading;
const factory ChangeCoverPopoverState.loaded(
List<String> imageNames,
) = Loaded;
}

View File

@ -156,10 +156,7 @@ class _AddCoverButtonState extends State<_AddCoverButton> {
leftIconSize: const Size.square(18), leftIconSize: const Size.square(18),
onTap: widget.onTap, onTap: widget.onTap,
useIntrinsicWidth: true, useIntrinsicWidth: true,
leftIcon: svgWidget( leftIcon: const FlowySvg(name: 'editor/image'),
'editor/image',
color: Theme.of(context).colorScheme.onSurface,
),
text: FlowyText.regular( text: FlowyText.regular(
LocaleKeys.document_plugins_cover_addCover.tr(), LocaleKeys.document_plugins_cover_addCover.tr(),
), ),
@ -174,7 +171,7 @@ class _AddCoverButtonState extends State<_AddCoverButton> {
useIntrinsicWidth: true, useIntrinsicWidth: true,
leftIcon: Icon( leftIcon: Icon(
Icons.emoji_emotions_outlined, Icons.emoji_emotions_outlined,
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
size: 18, size: 18,
), ),
text: FlowyText.regular(LocaleKeys text: FlowyText.regular(LocaleKeys
@ -197,8 +194,7 @@ class _AddCoverButtonState extends State<_AddCoverButton> {
child: FlowyButton( child: FlowyButton(
leftIconSize: const Size.square(18), leftIconSize: const Size.square(18),
useIntrinsicWidth: true, useIntrinsicWidth: true,
leftIcon: Icon(Icons.emoji_emotions_outlined, leftIcon: const Icon(Icons.emoji_emotions_outlined,
color: Theme.of(context).colorScheme.onSurface,
size: 18), size: 18),
text: FlowyText.regular( text: FlowyText.regular(
LocaleKeys.document_plugins_cover_addIcon.tr()), LocaleKeys.document_plugins_cover_addIcon.tr()),
@ -400,7 +396,7 @@ class _CoverImageState extends State<_CoverImage> {
popoverController.show(); popoverController.show();
}, },
hoverColor: Theme.of(context).colorScheme.surface, hoverColor: Theme.of(context).colorScheme.surface,
textColor: Theme.of(context).colorScheme.onSurface, textColor: Theme.of(context).colorScheme.tertiary,
fillColor: Theme.of(context).colorScheme.surface.withOpacity(0.8), fillColor: Theme.of(context).colorScheme.surface.withOpacity(0.8),
width: 120, width: 120,
height: 28, height: 28,
@ -422,7 +418,7 @@ class _CoverImageState extends State<_CoverImage> {
width: 28, width: 28,
icon: svgWidget( icon: svgWidget(
'editor/delete', 'editor/delete',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).colorScheme.tertiary,
), ),
onPressed: () { onPressed: () {
widget.onCoverChanged(CoverSelectionType.initial, null); widget.onCoverChanged(CoverSelectionType.initial, null);

View File

@ -17,7 +17,7 @@ SelectionMenuItem gridMenuItem = SelectionMenuItem(
: editorState.editorStyle.selectionMenuItemIconColor, : editorState.editorStyle.selectionMenuItemIconColor,
); );
}, },
keywords: ['referenced grid'], keywords: ['referenced', 'grid'],
handler: (editorState, menuService, context) { handler: (editorState, menuService, context) {
showLinkToPageMenu( showLinkToPageMenu(
editorState, editorState,

View File

@ -45,13 +45,9 @@ class MenuTrash extends StatelessWidget {
Widget _render(BuildContext context) { Widget _render(BuildContext context) {
return Row( return Row(
children: [ children: [
SizedBox( const FlowySvg(
width: 16, size: Size(16, 16),
height: 16, name: 'home/trash',
child: svgWidget(
"home/trash",
color: Theme.of(context).colorScheme.onSurface,
),
), ),
const HSpace(6), const HSpace(6),
FlowyText.medium(LocaleKeys.trash_text.tr()), FlowyText.medium(LocaleKeys.trash_text.tr()),

View File

@ -43,7 +43,7 @@ class TrashCell extends StatelessWidget {
iconPadding: const EdgeInsets.all(5), iconPadding: const EdgeInsets.all(5),
icon: svgWidget( icon: svgWidget(
"editor/restore", "editor/restore",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
const HSpace(20), const HSpace(20),
@ -53,7 +53,7 @@ class TrashCell extends StatelessWidget {
iconPadding: const EdgeInsets.all(5), iconPadding: const EdgeInsets.all(5),
icon: svgWidget( icon: svgWidget(
"editor/delete", "editor/delete",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
], ],

View File

@ -90,6 +90,7 @@ class _TrashPageState extends State<TrashPage> {
FlowyText.semibold( FlowyText.semibold(
LocaleKeys.trash_text.tr(), LocaleKeys.trash_text.tr(),
fontSize: FontSizes.s16, fontSize: FontSizes.s16,
color: Theme.of(context).colorScheme.tertiary,
), ),
const Spacer(), const Spacer(),
IntrinsicWidth( IntrinsicWidth(
@ -97,7 +98,7 @@ class _TrashPageState extends State<TrashPage> {
text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr()), text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr()),
leftIcon: svgWidget( leftIcon: svgWidget(
'editor/restore', 'editor/restore',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
onTap: () => context.read<TrashBloc>().add( onTap: () => context.read<TrashBloc>().add(
const TrashEvent.restoreAll(), const TrashEvent.restoreAll(),
@ -110,7 +111,7 @@ class _TrashPageState extends State<TrashPage> {
text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr()), text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr()),
leftIcon: svgWidget( leftIcon: svgWidget(
'editor/delete', 'editor/delete',
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
onTap: () => onTap: () =>
context.read<TrashBloc>().add(const TrashEvent.deleteAll()), context.read<TrashBloc>().add(const TrashEvent.deleteAll()),

View File

@ -46,6 +46,7 @@ class InitAppWidgetTask extends LaunchTask {
Locale('sv'), Locale('sv'),
Locale('tr', 'TR'), Locale('tr', 'TR'),
Locale('zh', 'CN'), Locale('zh', 'CN'),
Locale('zh', 'TW'),
], ],
path: 'assets/translations', path: 'assets/translations',
fallbackLocale: const Locale('en'), fallbackLocale: const Locale('en'),

View File

@ -2,9 +2,7 @@ import 'dart:io';
import 'package:appflowy/util/file_picker/file_picker_service.dart'; import 'package:appflowy/util/file_picker/file_picker_service.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/text_field.dart';
import 'package:flowy_infra_ui/widget/rounded_button.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
@ -36,10 +34,7 @@ class _FolderWidgetState extends State<FolderWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return _mapIndexToWidget(context);
height: 250,
child: _mapIndexToWidget(context),
);
} }
Widget _mapIndexToWidget(BuildContext context) { Widget _mapIndexToWidget(BuildContext context) {
@ -86,37 +81,24 @@ class FolderOptionsWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView( return Column(
shrinkWrap: true, children: [
children: <Widget>[ _FolderCard(
Card( title: LocaleKeys.settings_files_createNewFolder.tr(),
child: ListTile( subtitle: LocaleKeys.settings_files_createNewFolderDesc.tr(),
title: FlowyText.medium( trailing: _buildTextButton(
LocaleKeys.settings_files_createNewFolder.tr(), context,
), LocaleKeys.settings_files_create.tr(),
subtitle: FlowyText.regular( onPressedCreate,
LocaleKeys.settings_files_createNewFolderDesc.tr(),
),
trailing: _buildTextButton(
context,
LocaleKeys.settings_files_create.tr(),
onPressedCreate,
),
), ),
), ),
Card( _FolderCard(
child: ListTile( title: LocaleKeys.settings_files_openFolder.tr(),
title: FlowyText.medium( subtitle: LocaleKeys.settings_files_openFolderDesc.tr(),
LocaleKeys.settings_files_openFolder.tr(), trailing: _buildTextButton(
), context,
subtitle: FlowyText.regular( LocaleKeys.settings_files_open.tr(),
LocaleKeys.settings_files_openFolderDesc.tr(), onPressedOpen,
),
trailing: _buildTextButton(
context,
LocaleKeys.settings_files_open.tr(),
onPressedOpen,
),
), ),
), ),
], ],
@ -164,56 +146,55 @@ class CreateFolderWidgetState extends State<CreateFolderWidget> {
label: const Text('Back'), label: const Text('Back'),
), ),
), ),
Card( _FolderCard(
child: ListTile( title: LocaleKeys.settings_files_location.tr(),
title: FlowyText.medium( subtitle: LocaleKeys.settings_files_locationDesc.tr(),
LocaleKeys.settings_files_location.tr(), trailing: SizedBox(
), width: 120,
subtitle: FlowyText.regular( child: FlowyTextField(
LocaleKeys.settings_files_locationDesc.tr(), hintText: LocaleKeys.settings_files_folderHintText.tr(),
), onChanged: (name) => _folderName = name,
trailing: SizedBox( onSubmitted: (name) => setState(
width: 100, () => _folderName = name,
height: 36,
child: FlowyTextField(
hintText: LocaleKeys.settings_files_folderHintText.tr(),
onChanged: (name) {
_folderName = name;
},
onSubmitted: (name) {
setState(() {
_folderName = name;
});
},
), ),
), ),
), ),
), ),
Card( _FolderCard(
child: ListTile( title: LocaleKeys.settings_files_folderPath.tr(),
title: FlowyText.medium(LocaleKeys.settings_files_folderPath.tr()), subtitle: _path,
subtitle: FlowyText.regular(_path), trailing: _buildTextButton(
trailing: _buildTextButton( context,
context, LocaleKeys.settings_files_browser.tr(), () async { LocaleKeys.settings_files_browser.tr(),
() async {
final dir = await getIt<FilePickerService>().getDirectoryPath(); final dir = await getIt<FilePickerService>().getDirectoryPath();
if (dir != null) { if (dir != null) {
setState(() { setState(() => directory = dir);
directory = dir;
});
} }
}), },
), ),
), ),
Card( const VSpace(4.0),
child: _buildTextButton( Padding(
context, LocaleKeys.settings_files_create.tr(), () async { padding: const EdgeInsets.symmetric(horizontal: 4.0),
if (_path.isEmpty) { child: Row(
_showToast(LocaleKeys.settings_files_locationCannotBeEmpty.tr()); children: [
} else { _buildTextButton(
await getIt<SettingsLocationCubit>().setLocation(_path); context,
await widget.onPressedCreate(); LocaleKeys.settings_files_create.tr(),
} () async {
}), if (_path.isEmpty) {
_showToast(
LocaleKeys.settings_files_locationCannotBeEmpty.tr(),
);
} else {
await getIt<SettingsLocationCubit>().setLocation(_path);
await widget.onPressedCreate();
}
},
),
],
),
) )
], ],
); );
@ -240,12 +221,70 @@ class CreateFolderWidgetState extends State<CreateFolderWidget> {
Widget _buildTextButton( Widget _buildTextButton(
BuildContext context, String title, VoidCallback onPressed) { BuildContext context, String title, VoidCallback onPressed) {
return SizedBox( return FlowyTextButton(
width: 70, title,
height: 36, onPressed: onPressed,
child: RoundedTextButton( fillColor: Theme.of(context).colorScheme.primary,
title: title, fontColor: Theme.of(context).colorScheme.onPrimary,
onPressed: onPressed, hoverColor: Theme.of(context).colorScheme.primaryContainer,
),
); );
} }
class _FolderCard extends StatelessWidget {
const _FolderCard({
Key? key,
required this.title,
required this.subtitle,
this.trailing,
}) : super(key: key);
final String title;
final String subtitle;
final Widget? trailing;
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 4.0,
horizontal: 16.0,
),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FlowyText.medium(
title,
),
Row(
children: [
Flexible(
child: Text(
subtitle,
overflow: TextOverflow.ellipsis,
style:
Theme.of(context).textTheme.bodyMedium!.copyWith(
fontWeight: FontWeight.w400,
),
),
),
],
),
],
),
),
if (trailing != null) ...[
const HSpace(40),
trailing!,
],
],
),
),
);
}
}

View File

@ -1,9 +1,8 @@
import 'package:appflowy/core/frameless_window.dart';
import 'package:dartz/dartz.dart' as dartz; import 'package:dartz/dartz.dart' as dartz;
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/widget/rounded_button.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
@ -39,6 +38,7 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: const _SkipLoginMoveWindow(),
body: Center( body: Center(
child: _renderBody(context), child: _renderBody(context),
), ),
@ -54,9 +54,13 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
logoSize: const Size.square(60), logoSize: const Size.square(60),
), ),
const VSpace(40), const VSpace(40),
SizedBox( Row(
width: 250, mainAxisAlignment: MainAxisAlignment.center,
child: GoButton(onPressed: () => _autoRegister(context)), children: [
GoButton(
onPressed: () => _autoRegister(context),
),
],
), ),
const VSpace(20), const VSpace(20),
SizedBox( SizedBox(
@ -72,18 +76,15 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
}, },
), ),
), ),
const VSpace(20), const Spacer(),
SizedBox( _buildSubscribeButtons(context),
width: 400,
child: _buildSubscribeButtons(context),
),
], ],
); );
} }
Row _buildSubscribeButtons(BuildContext context) { Row _buildSubscribeButtons(BuildContext context) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
FlowyTextButton( FlowyTextButton(
LocaleKeys.githubStarText.tr(), LocaleKeys.githubStarText.tr(),
@ -95,6 +96,7 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
onPressed: () => onPressed: () =>
_launchURL('https://github.com/AppFlowy-IO/appflowy'), _launchURL('https://github.com/AppFlowy-IO/appflowy'),
), ),
const HSpace(20),
FlowyTextButton( FlowyTextButton(
LocaleKeys.subscribeNewsletterText.tr(), LocaleKeys.subscribeNewsletterText.tr(),
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -149,19 +151,41 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
class GoButton extends StatelessWidget { class GoButton extends StatelessWidget {
final VoidCallback onPressed; final VoidCallback onPressed;
const GoButton({ const GoButton({
Key? key, super.key,
required this.onPressed, required this.onPressed,
}) : super(key: key); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return RoundedTextButton( return FlowyTextButton(
title: LocaleKeys.letsGoButtonText.tr(), LocaleKeys.letsGoButtonText.tr(),
fontSize: FontSizes.s16, fontSize: FontSizes.s16,
height: 50, padding: const EdgeInsets.symmetric(horizontal: 80, vertical: 12.0),
borderRadius: Corners.s10Border,
onPressed: onPressed, onPressed: onPressed,
fillColor: Theme.of(context).colorScheme.primary,
fontColor: Theme.of(context).colorScheme.onPrimary,
hoverColor: Theme.of(context).colorScheme.primaryContainer,
); );
} }
} }
class _SkipLoginMoveWindow extends StatelessWidget
implements PreferredSizeWidget {
const _SkipLoginMoveWindow();
@override
Widget build(BuildContext context) {
return Row(
children: const [
Expanded(
child: MoveWindowDetector(),
),
],
);
}
@override
Size get preferredSize => const Size.fromHeight(55.0);
}

View File

@ -49,6 +49,7 @@ class FlowyLogoTitle extends StatelessWidget {
FlowyText.semibold( FlowyText.semibold(
title, title,
fontSize: FontSizes.s24, fontSize: FontSizes.s24,
color: Theme.of(context).colorScheme.tertiary,
), ),
], ],
), ),

View File

@ -212,14 +212,20 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
return ThemeData( return ThemeData(
brightness: brightness, brightness: brightness,
textTheme: textTheme: _getTextTheme(fontFamily: fontFamily, fontColor: theme.text),
_getTextTheme(fontFamily: fontFamily, fontColor: theme.shader1),
textSelectionTheme: TextSelectionThemeData( textSelectionTheme: TextSelectionThemeData(
cursorColor: theme.main2, cursorColor: theme.main2,
selectionHandleColor: theme.main2, selectionHandleColor: theme.main2,
), ),
primaryIconTheme: IconThemeData(color: theme.hover), iconTheme: IconThemeData(color: theme.icon),
iconTheme: IconThemeData(color: theme.shader1), tooltipTheme: TooltipThemeData(
textStyle: _getFontStyle(
fontFamily: fontFamily,
fontSize: FontSizes.s11,
fontWeight: FontWeight.w400,
fontColor: theme.surface,
),
),
scrollbarTheme: ScrollbarThemeData( scrollbarTheme: ScrollbarThemeData(
thumbColor: MaterialStateProperty.all(theme.shader3), thumbColor: MaterialStateProperty.all(theme.shader3),
thickness: MaterialStateProperty.resolveWith((states) { thickness: MaterialStateProperty.resolveWith((states) {
@ -239,30 +245,38 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
), ),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
canvasColor: theme.shader6, canvasColor: theme.shader6,
dividerColor: theme.shader6, dividerColor: theme.divider,
hintColor: theme.shader3, hintColor: theme.hint,
//action item hover color
hoverColor: theme.hoverBG2,
disabledColor: theme.shader4, disabledColor: theme.shader4,
highlightColor: theme.main1, highlightColor: theme.main1,
indicatorColor: theme.main1, indicatorColor: theme.main1,
toggleableActiveColor: theme.main1, toggleableActiveColor: theme.main1,
cardColor: theme.input,
colorScheme: ColorScheme( colorScheme: ColorScheme(
brightness: brightness, brightness: brightness,
primary: theme.main1, primary: theme.primary,
onPrimary: _white, onPrimary: theme.onPrimary,
primaryContainer: theme.main2, primaryContainer: theme.main2,
onPrimaryContainer: _white, onPrimaryContainer: _white,
secondary: theme.hover, // page title hover color
secondary: theme.hoverBG1,
onSecondary: theme.shader1, onSecondary: theme.shader1,
// setting value hover color
secondaryContainer: theme.selector, secondaryContainer: theme.selector,
onSecondaryContainer: theme.shader1, onSecondaryContainer: theme.topbarBg,
tertiary: theme.shader7,
tertiaryContainer: theme.questionBubbleBG,
background: theme.surface, background: theme.surface,
onBackground: theme.shader1, onBackground: theme.text,
surface: theme.surface, surface: theme.surface,
onSurface: theme.shader1, // text&icon color when it is hovered
onSurface: theme.hoverFG,
onError: theme.shader7, onError: theme.shader7,
error: theme.red, error: theme.red,
outline: theme.shader4, outline: theme.shader4,
surfaceVariant: theme.bg1, surfaceVariant: theme.sidebarBg,
shadow: theme.shadow, shadow: theme.shadow,
), ),
extensions: [ extensions: [
@ -278,7 +292,7 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
tint7: theme.tint7, tint7: theme.tint7,
tint8: theme.tint8, tint8: theme.tint8,
tint9: theme.tint9, tint9: theme.tint9,
greyHover: theme.bg2, greyHover: theme.hoverBG1,
greySelect: theme.bg3, greySelect: theme.bg3,
lightGreyHover: theme.shader6, lightGreyHover: theme.shader6,
toggleOffFill: theme.shader5, toggleOffFill: theme.shader5,

View File

@ -36,7 +36,7 @@ extension ViewExtension on ViewPB {
Widget renderThumbnail({Color? iconColor}) { Widget renderThumbnail({Color? iconColor}) {
String thumbnail = "file_icon"; String thumbnail = "file_icon";
final Widget widget = svgWidget(thumbnail, color: iconColor); final Widget widget = FlowySvg(name: thumbnail);
return widget; return widget;
} }

View File

@ -199,7 +199,7 @@ class HomeTopBar extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.onSecondaryContainer,
height: HomeSizes.topBarHeight, height: HomeSizes.topBarHeight,
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,

View File

@ -18,9 +18,14 @@ class NewAppButton extends StatelessWidget {
LocaleKeys.newPageText.tr(), LocaleKeys.newPageText.tr(),
fillColor: Colors.transparent, fillColor: Colors.transparent,
hoverColor: Colors.transparent, hoverColor: Colors.transparent,
fontColor: Theme.of(context).colorScheme.onSurfaceVariant, fontColor: Theme.of(context).colorScheme.tertiary,
onPressed: () async => await _showCreateAppDialog(context), onPressed: () async => await _showCreateAppDialog(context),
heading: svgWidget("home/new_app", size: const Size(16, 16)), heading: Theme.of(context).brightness == Brightness.light
? svgWidget("home/new_app", size: const Size(16, 16))
: svgWidget(
"home/new_app_dark",
size: const Size(16, 16),
),
padding: EdgeInsets.symmetric(horizontal: Insets.l, vertical: 20), padding: EdgeInsets.symmetric(horizontal: Insets.l, vertical: 20),
); );

View File

@ -6,9 +6,9 @@ import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
import 'package:appflowy_editor/appflowy_editor.dart' show Document; import 'package:appflowy_editor/appflowy_editor.dart' show Document;
import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@ -50,13 +50,19 @@ class AddButton extends StatelessWidget {
actions: actions, actions: actions,
offset: const Offset(0, 8), offset: const Offset(0, 8),
buildChild: (controller) { buildChild: (controller) {
return FlowyIconButton( return SizedBox(
width: 22, width: 22,
onPressed: () => controller.show(), child: InkWell(
icon: svgWidget( onTap: () => controller.show(),
"home/add", child: FlowyHover(
color: Theme.of(context).colorScheme.onSurface, style: HoverStyle(
).padding(horizontal: 3, vertical: 3), hoverColor: AFThemeExtension.of(context).greySelect,
),
builder: (context, onHover) => const FlowySvg(
name: 'home/add',
),
),
),
); );
}, },
onSelected: (action, controller) { onSelected: (action, controller) {
@ -83,8 +89,7 @@ class AddButtonActionWrapper extends ActionCell {
AddButtonActionWrapper({required this.pluginBuilder}); AddButtonActionWrapper({required this.pluginBuilder});
@override @override
Widget? leftIcon(Color iconColor) => Widget? leftIcon(Color iconColor) => FlowySvg(name: pluginBuilder.menuIcon);
svgWidget(pluginBuilder.menuIcon, color: iconColor);
@override @override
String get name => pluginBuilder.menuName; String get name => pluginBuilder.menuName;
@ -100,9 +105,8 @@ class ImportActionWrapper extends ActionCell {
}); });
@override @override
Widget? leftIcon(Color iconColor) => svgWidget( Widget? leftIcon(Color iconColor) => const FlowySvg(
'editor/import', name: 'editor/import',
color: iconColor,
); );
@override @override

View File

@ -5,7 +5,6 @@ import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:expandable/expandable.dart'; import 'package:expandable/expandable.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra/icon_data.dart'; import 'package:flowy_infra/icon_data.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
@ -15,7 +14,6 @@ import 'package:appflowy/workspace/application/app/app_bloc.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:textstyle_extensions/textstyle_extensions.dart';
import '../menu_app.dart'; import '../menu_app.dart';
import 'add_button.dart'; import 'add_button.dart';
@ -58,7 +56,7 @@ class MenuAppHeader extends StatelessWidget {
theme: ExpandableThemeData( theme: ExpandableThemeData(
expandIcon: FlowyIconData.drop_down_show, expandIcon: FlowyIconData.drop_down_show,
collapseIcon: FlowyIconData.drop_down_hide, collapseIcon: FlowyIconData.drop_down_hide,
iconColor: Theme.of(context).colorScheme.onSurface, iconColor: Theme.of(context).colorScheme.tertiary,
iconSize: MenuAppSizes.iconSize, iconSize: MenuAppSizes.iconSize,
iconPadding: const EdgeInsets.fromLTRB(0, 0, 10, 0), iconPadding: const EdgeInsets.fromLTRB(0, 0, 10, 0),
hasIcon: false, hasIcon: false,
@ -104,7 +102,6 @@ class MenuAppHeader extends StatelessWidget {
Widget _renderCreateViewButton(BuildContext context) { Widget _renderCreateViewButton(BuildContext context) {
return Tooltip( return Tooltip(
message: LocaleKeys.menuAppHeader_addPageTooltip.tr(), message: LocaleKeys.menuAppHeader_addPageTooltip.tr(),
textStyle: AFThemeExtension.of(context).caption.textColor(Colors.white),
child: AddButton( child: AddButton(
onSelected: (pluginBuilder, document) { onSelected: (pluginBuilder, document) {
context.read<AppBloc>().add( context.read<AppBloc>().add(
@ -139,9 +136,9 @@ extension AppDisclosureExtension on AppDisclosureAction {
Widget icon(Color iconColor) { Widget icon(Color iconColor) {
switch (this) { switch (this) {
case AppDisclosureAction.rename: case AppDisclosureAction.rename:
return svgWidget('editor/edit', color: iconColor); return const FlowySvg(name: 'editor/edit');
case AppDisclosureAction.delete: case AppDisclosureAction.delete:
return svgWidget('editor/delete', color: iconColor); return const FlowySvg(name: 'editor/delete');
} }
} }
} }
@ -174,6 +171,7 @@ class AppActionList extends StatelessWidget {
builder: (context, app) => FlowyText.medium( builder: (context, app) => FlowyText.medium(
app.name, app.name,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
color: Theme.of(context).colorScheme.tertiary,
), ),
), ),
); );

View File

@ -24,6 +24,7 @@ Future<void> showImportPanel(
title: FlowyText.semibold( title: FlowyText.semibold(
LocaleKeys.moreAction_import.tr(), LocaleKeys.moreAction_import.tr(),
fontSize: 20, fontSize: 20,
color: Theme.of(context).colorScheme.tertiary,
), ),
content: _ImportPanel(importCallback: callback), content: _ImportPanel(importCallback: callback),
contentPadding: const EdgeInsets.symmetric( contentPadding: const EdgeInsets.symmetric(

View File

@ -4,7 +4,6 @@ import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/presentation/home/menu/menu.dart'; import 'package:appflowy/workspace/presentation/home/menu/menu.dart';
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
@ -51,7 +50,7 @@ class ViewSectionItem extends StatelessWidget {
onTap: () => onSelected(blocContext.read<ViewBloc>().state.view), onTap: () => onSelected(blocContext.read<ViewBloc>().state.view),
child: FlowyHover( child: FlowyHover(
style: HoverStyle( style: HoverStyle(
hoverColor: AFThemeExtension.of(context).greySelect, hoverColor: Theme.of(context).colorScheme.secondary,
), ),
// If current state.isEditing is true, the hover should not // If current state.isEditing is true, the hover should not
// rebuild when onEnter/onExit events happened. // rebuild when onEnter/onExit events happened.
@ -60,7 +59,6 @@ class ViewSectionItem extends StatelessWidget {
blocContext, blocContext,
onHover, onHover,
state, state,
Theme.of(context).colorScheme.onSurface,
), ),
isSelected: () => state.isEditing || isSelected, isSelected: () => state.isEditing || isSelected,
), ),
@ -75,13 +73,12 @@ class ViewSectionItem extends StatelessWidget {
BuildContext blocContext, BuildContext blocContext,
bool onHover, bool onHover,
ViewState state, ViewState state,
Color iconColor,
) { ) {
List<Widget> children = [ List<Widget> children = [
SizedBox( SizedBox(
width: 16, width: 16,
height: 16, height: 16,
child: state.view.renderThumbnail(iconColor: iconColor), child: state.view.renderThumbnail(),
), ),
const HSpace(2), const HSpace(2),
Expanded( Expanded(
@ -154,11 +151,11 @@ extension ViewDisclosureExtension on ViewDisclosureAction {
Widget icon(Color iconColor) { Widget icon(Color iconColor) {
switch (this) { switch (this) {
case ViewDisclosureAction.rename: case ViewDisclosureAction.rename:
return svgWidget('editor/edit', color: iconColor); return const FlowySvg(name: 'editor/edit');
case ViewDisclosureAction.delete: case ViewDisclosureAction.delete:
return svgWidget('editor/delete', color: iconColor); return const FlowySvg(name: 'editor/delete');
case ViewDisclosureAction.duplicate: case ViewDisclosureAction.duplicate:
return svgWidget('editor/copy', color: iconColor); return const FlowySvg(name: 'editor/copy');
} }
} }
} }
@ -186,7 +183,7 @@ class ViewDisclosureButton extends StatelessWidget {
width: 26, width: 26,
icon: svgWidget( icon: svgWidget(
"editor/details", "editor/details",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
onPressed: () { onPressed: () {
onEdit(true); onEdit(true);

View File

@ -229,7 +229,7 @@ class MenuTopBar extends StatelessWidget {
iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4), iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4),
icon: svgWidget( icon: svgWidget(
"home/hide_menu", "home/hide_menu",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
), ),
) )

View File

@ -2,7 +2,6 @@ import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/menu/menu_user_bloc.dart'; import 'package:appflowy/workspace/application/menu/menu_user_bloc.dart';
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart'; import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart'; import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
@ -13,7 +12,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:textstyle_extensions/textstyle_extensions.dart';
class MenuUser extends StatelessWidget { class MenuUser extends StatelessWidget {
final UserProfilePB user; final UserProfilePB user;
@ -69,6 +67,7 @@ class MenuUser extends StatelessWidget {
return FlowyText.medium( return FlowyText.medium(
name, name,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
color: Theme.of(context).colorScheme.tertiary,
); );
} }
@ -76,7 +75,6 @@ class MenuUser extends StatelessWidget {
final userProfile = context.read<MenuUserBloc>().state.userProfile; final userProfile = context.read<MenuUserBloc>().state.userProfile;
return Tooltip( return Tooltip(
message: LocaleKeys.settings_menu_open.tr(), message: LocaleKeys.settings_menu_open.tr(),
textStyle: AFThemeExtension.of(context).caption.textColor(Colors.white),
child: IconButton( child: IconButton(
onPressed: () { onPressed: () {
showDialog( showDialog(
@ -90,7 +88,7 @@ class MenuUser extends StatelessWidget {
dimension: 20, dimension: 20,
child: svgWidget( child: svgWidget(
"home/settings", "home/settings",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).colorScheme.tertiary,
), ),
), ),
), ),

View File

@ -6,14 +6,12 @@ import 'package:appflowy/workspace/presentation/home/home_stack.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:textstyle_extensions/textstyle_extensions.dart';
typedef NaviAction = void Function(); typedef NaviAction = void Function();
@ -87,7 +85,7 @@ class FlowyNavigation extends StatelessWidget {
iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2), iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
icon: svgWidget( icon: svgWidget(
"home/hide_menu", "home/hide_menu",
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).iconTheme.color,
), ),
)), )),
); );
@ -180,11 +178,9 @@ TextSpan sidebarTooltipTextSpan(BuildContext context, String hintText) =>
children: [ children: [
TextSpan( TextSpan(
text: "$hintText\n", text: "$hintText\n",
style: AFThemeExtension.of(context).callout.textColor(Colors.white),
), ),
TextSpan( TextSpan(
text: Platform.isMacOS ? "⌘+\\" : "Ctrl+\\", text: Platform.isMacOS ? "⌘+\\" : "Ctrl+\\",
style: AFThemeExtension.of(context).caption.textColor(Colors.white60),
), ),
], ],
); );

View File

@ -32,6 +32,7 @@ class SettingsDialog extends StatelessWidget {
LocaleKeys.settings_title.tr(), LocaleKeys.settings_title.tr(),
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: Theme.of(context).colorScheme.tertiary,
), ),
), ),
child: ScaffoldMessenger( child: ScaffoldMessenger(
@ -54,7 +55,9 @@ class SettingsDialog extends StatelessWidget {
context.read<SettingsDialogBloc>().state.page, context.read<SettingsDialogBloc>().state.page,
), ),
), ),
const VerticalDivider(), VerticalDivider(
color: Theme.of(context).dividerColor,
),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
child: getSettingsView( child: getSettingsView(

View File

@ -50,8 +50,8 @@ class ThemeSetting extends StatelessWidget {
direction: PopoverDirection.bottomWithRightAligned, direction: PopoverDirection.bottomWithRightAligned,
child: FlowyTextButton( child: FlowyTextButton(
currentTheme, currentTheme,
fontColor: Theme.of(context).colorScheme.onBackground,
fillColor: Colors.transparent, fillColor: Colors.transparent,
hoverColor: Theme.of(context).colorScheme.secondary,
onPressed: () {}, onPressed: () {},
), ),
popupBuilder: (BuildContext context) { popupBuilder: (BuildContext context) {
@ -107,8 +107,8 @@ class ThemeModeSetting extends StatelessWidget {
direction: PopoverDirection.bottomWithRightAligned, direction: PopoverDirection.bottomWithRightAligned,
child: FlowyTextButton( child: FlowyTextButton(
_themeModeLabelText(currentThemeMode), _themeModeLabelText(currentThemeMode),
fontColor: Theme.of(context).colorScheme.onBackground,
fillColor: Colors.transparent, fillColor: Colors.transparent,
hoverColor: Theme.of(context).colorScheme.secondary,
onPressed: () {}, onPressed: () {},
), ),
popupBuilder: (BuildContext context) { popupBuilder: (BuildContext context) {

View File

@ -47,7 +47,7 @@ class _LanguageSelectorDropdownState extends State<LanguageSelectorDropdown> {
void hoverEnterLanguage() { void hoverEnterLanguage() {
setState(() { setState(() {
currHoverColor = Theme.of(context).colorScheme.primary; currHoverColor = Theme.of(context).colorScheme.secondaryContainer;
}); });
} }
@ -67,6 +67,7 @@ class _LanguageSelectorDropdownState extends State<LanguageSelectorDropdown> {
padding: const EdgeInsets.symmetric(horizontal: 6), padding: const EdgeInsets.symmetric(horizontal: 6),
child: DropdownButton<Locale>( child: DropdownButton<Locale>(
value: context.locale, value: context.locale,
dropdownColor: Theme.of(context).cardColor,
onChanged: (locale) { onChanged: (locale) {
context context
.read<AppearanceSettingsCubit>() .read<AppearanceSettingsCubit>()
@ -80,7 +81,10 @@ class _LanguageSelectorDropdownState extends State<LanguageSelectorDropdown> {
value: locale, value: locale,
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
child: FlowyText.medium(languageFromLocale(locale)), child: FlowyText.medium(
languageFromLocale(locale),
color: Theme.of(context).colorScheme.tertiary,
),
), ),
); );
}).toList(), }).toList(),

View File

@ -1,5 +1,6 @@
import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dart'; import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -21,29 +22,32 @@ class SettingsMenuElement extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return FlowyHover(
leading: Icon( style: HoverStyle(
icon, hoverColor: Theme.of(context).colorScheme.primary,
size: 16,
color: page == selectedPage
? Theme.of(context).colorScheme.onSurface
: Theme.of(context).colorScheme.onSurface,
), ),
onTap: () { child: ListTile(
changeSelectedPage(page); leading: Icon(icon,
}, size: 16,
selected: page == selectedPage, color: page == selectedPage
selectedColor: Theme.of(context).colorScheme.onSurface, ? Theme.of(context).colorScheme.onSurface
selectedTileColor: Theme.of(context).colorScheme.primaryContainer, : null),
hoverColor: Theme.of(context).colorScheme.primary, onTap: () {
shape: RoundedRectangleBorder( changeSelectedPage(page);
borderRadius: BorderRadius.circular(5), },
), selected: page == selectedPage,
minLeadingWidth: 0, selectedColor: Theme.of(context).colorScheme.onSurface,
title: FlowyText.semibold( selectedTileColor: Theme.of(context).colorScheme.primary,
label, shape: RoundedRectangleBorder(
fontSize: FontSizes.s14, borderRadius: BorderRadius.circular(5),
overflow: TextOverflow.ellipsis, ),
minLeadingWidth: 0,
title: FlowyText.semibold(label,
fontSize: FontSizes.s14,
overflow: TextOverflow.ellipsis,
color: page == selectedPage
? Theme.of(context).colorScheme.onSurface
: null),
), ),
); );
} }

View File

@ -48,6 +48,9 @@ class BubbleActionList extends StatelessWidget {
'?', '?',
tooltip: LocaleKeys.questionBubble_help.tr(), tooltip: LocaleKeys.questionBubble_help.tr(),
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontColor: Theme.of(context).colorScheme.tertiary,
fillColor: Theme.of(context).colorScheme.tertiaryContainer,
hoverColor: Theme.of(context).colorScheme.tertiaryContainer,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
radius: Corners.s10Border, radius: Corners.s10Border,
onPressed: () => controller.show(), onPressed: () => controller.show(),
@ -200,7 +203,7 @@ extension QuestionBubbleExtension on BubbleAction {
case BubbleAction.debug: case BubbleAction.debug:
return '🐛'; return '🐛';
case BubbleAction.shortcuts: case BubbleAction.shortcuts:
return '⌨️'; return '📋';
} }
} }
} }

View File

@ -8,6 +8,7 @@ import 'package:appflowy_editor/src/render/link_menu/link_menu.dart';
import 'package:appflowy_editor/src/extensions/text_node_extensions.dart'; import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
import 'package:appflowy_editor/src/extensions/editor_state_extensions.dart'; import 'package:appflowy_editor/src/extensions/editor_state_extensions.dart';
import 'package:appflowy_editor/src/service/default_text_operations/format_rich_text_style.dart'; import 'package:appflowy_editor/src/service/default_text_operations/format_rich_text_style.dart';
import 'dart:io' show Platform;
import 'package:flutter/material.dart' hide Overlay, OverlayEntry; import 'package:flutter/material.dart' hide Overlay, OverlayEntry;
@ -127,7 +128,9 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem( ToolbarItem(
id: 'appflowy.toolbar.bold', id: 'appflowy.toolbar.bold',
type: 2, type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.bold, tooltipsMessage: AppFlowyEditorLocalizations.current.bold +
"\n" +
(Platform.isMacOS ? "⌘ + B" : "CTRL + B"),
iconBuilder: (isHighlight) => FlowySvg( iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/bold', name: 'toolbar/bold',
color: isHighlight ? Colors.lightBlue : null, color: isHighlight ? Colors.lightBlue : null,
@ -143,7 +146,9 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem( ToolbarItem(
id: 'appflowy.toolbar.italic', id: 'appflowy.toolbar.italic',
type: 2, type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.italic, tooltipsMessage: AppFlowyEditorLocalizations.current.italic +
"\n" +
(Platform.isMacOS ? "⌘ + I" : "CTRL + I"),
iconBuilder: (isHighlight) => FlowySvg( iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/italic', name: 'toolbar/italic',
color: isHighlight ? Colors.lightBlue : null, color: isHighlight ? Colors.lightBlue : null,
@ -159,7 +164,9 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem( ToolbarItem(
id: 'appflowy.toolbar.underline', id: 'appflowy.toolbar.underline',
type: 2, type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.underline, tooltipsMessage: AppFlowyEditorLocalizations.current.underline +
"\n" +
(Platform.isMacOS ? "⌘ + U" : "CTRL + U"),
iconBuilder: (isHighlight) => FlowySvg( iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/underline', name: 'toolbar/underline',
color: isHighlight ? Colors.lightBlue : null, color: isHighlight ? Colors.lightBlue : null,
@ -175,7 +182,9 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem( ToolbarItem(
id: 'appflowy.toolbar.strikethrough', id: 'appflowy.toolbar.strikethrough',
type: 2, type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.strikethrough, tooltipsMessage: AppFlowyEditorLocalizations.current.strikethrough +
"\n" +
(Platform.isMacOS ? "⌘ + SHIFT + S" : "CTRL + SHIFT + S"),
iconBuilder: (isHighlight) => FlowySvg( iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/strikethrough', name: 'toolbar/strikethrough',
color: isHighlight ? Colors.lightBlue : null, color: isHighlight ? Colors.lightBlue : null,
@ -191,7 +200,9 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem( ToolbarItem(
id: 'appflowy.toolbar.code', id: 'appflowy.toolbar.code',
type: 2, type: 2,
tooltipsMessage: AppFlowyEditorLocalizations.current.embedCode, tooltipsMessage: AppFlowyEditorLocalizations.current.embedCode +
"\n" +
(Platform.isMacOS ? "⌘ + E" : "CTRL + E"),
iconBuilder: (isHighlight) => FlowySvg( iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/code', name: 'toolbar/code',
color: isHighlight ? Colors.lightBlue : null, color: isHighlight ? Colors.lightBlue : null,
@ -238,10 +249,28 @@ List<ToolbarItem> defaultToolbarItems = [
), ),
handler: (editorState, context) => formatBulletedList(editorState), handler: (editorState, context) => formatBulletedList(editorState),
), ),
ToolbarItem(
id: 'appflowy.toolbar.number_list',
type: 3,
tooltipsMessage: AppFlowyEditorLocalizations.current.numberedList,
iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/number_list',
color: isHighlight ? Colors.lightBlue : null,
),
validator: _onlyShowInSingleTextSelection,
highlightCallback: (editorState) => _allSatisfy(
editorState,
BuiltInAttributeKey.subtype,
(value) => value == BuiltInAttributeKey.numberList,
),
handler: (editorState, context) => formatNumberedList(editorState),
),
ToolbarItem( ToolbarItem(
id: 'appflowy.toolbar.link', id: 'appflowy.toolbar.link',
type: 4, type: 4,
tooltipsMessage: AppFlowyEditorLocalizations.current.link, tooltipsMessage: AppFlowyEditorLocalizations.current.link +
"\n" +
(Platform.isMacOS ? "⌘ + K" : "CTRL + K"),
iconBuilder: (isHighlight) => FlowySvg( iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/link', name: 'toolbar/link',
color: isHighlight ? Colors.lightBlue : null, color: isHighlight ? Colors.lightBlue : null,
@ -257,7 +286,9 @@ List<ToolbarItem> defaultToolbarItems = [
ToolbarItem( ToolbarItem(
id: 'appflowy.toolbar.highlight', id: 'appflowy.toolbar.highlight',
type: 4, type: 4,
tooltipsMessage: AppFlowyEditorLocalizations.current.highlight, tooltipsMessage: AppFlowyEditorLocalizations.current.highlight +
"\n" +
(Platform.isMacOS ? "⌘ + SHIFT + H" : "CTRL + SHIFT + H"),
iconBuilder: (isHighlight) => FlowySvg( iconBuilder: (isHighlight) => FlowySvg(
name: 'toolbar/highlight', name: 'toolbar/highlight',
color: isHighlight ? Colors.lightBlue : null, color: isHighlight ? Colors.lightBlue : null,

View File

@ -21,6 +21,7 @@ class ToolbarItemWidget extends StatelessWidget {
width: 28, width: 28,
height: 28, height: 28,
child: Tooltip( child: Tooltip(
textAlign: TextAlign.center,
preferBelow: false, preferBelow: false,
message: item.tooltipsMessage, message: item.tooltipsMessage,
child: MouseRegion( child: MouseRegion(

View File

@ -91,6 +91,13 @@ void formatBulletedList(EditorState editorState) {
}); });
} }
void formatNumberedList(EditorState editorState) {
formatTextNodes(editorState, {
BuiltInAttributeKey.subtype: BuiltInAttributeKey.numberList,
BuiltInAttributeKey.number: 1,
});
}
/// Format the current selection with the given attributes. /// Format the current selection with the given attributes.
/// ///
/// If the selected nodes are not text nodes, this method will do nothing. /// If the selected nodes are not text nodes, this method will do nothing.

View File

@ -310,6 +310,47 @@ ShortcutEventHandler underscoreToItalicHandler = (editorState, event) {
return KeyEventResult.handled; return KeyEventResult.handled;
}; };
//Same functionality implemented via Asterisk - for italics
ShortcutEventHandler asteriskToItalicHandler = (editorState, event) {
final selectionService = editorState.service.selectionService;
final selection = selectionService.currentSelection.value;
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
if (selection == null || !selection.isSingle || textNodes.length != 1) {
return KeyEventResult.ignored;
}
final textNode = textNodes.first;
final text = textNode.toPlainText();
// Determine if an 'asterisk' already exists in the text node and only once.
final firstAsterisk = text.indexOf('*');
final lastAsterisk = text.lastIndexOf('*');
if (firstAsterisk == -1 ||
firstAsterisk != lastAsterisk ||
firstAsterisk == selection.start.offset - 1) {
return KeyEventResult.ignored;
}
final transaction = editorState.transaction
..deleteText(textNode, firstAsterisk, 1)
..formatText(
textNode,
firstAsterisk,
selection.end.offset - firstAsterisk - 1,
{
BuiltInAttributeKey.italic: true,
},
)
..afterSelection = Selection.collapsed(
Position(
path: textNode.path,
offset: selection.end.offset - 1,
),
);
editorState.apply(transaction);
return KeyEventResult.handled;
};
ShortcutEventHandler doubleAsteriskToBoldHandler = (editorState, event) { ShortcutEventHandler doubleAsteriskToBoldHandler = (editorState, event) {
final selectionService = editorState.service.selectionService; final selectionService = editorState.service.selectionService;
final selection = selectionService.currentSelection.value; final selection = selectionService.currentSelection.value;

View File

@ -307,6 +307,11 @@ List<ShortcutEvent> builtInShortcutEvents = [
character: '_', character: '_',
handler: underscoreToItalicHandler, handler: underscoreToItalicHandler,
), ),
ShortcutEvent(
key: 'Asterisk to italic',
character: '*',
handler: asteriskToItalicHandler,
),
ShortcutEvent( ShortcutEvent(
key: 'Double asterisk to bold', key: 'Double asterisk to bold',
character: '*', character: '*',

View File

@ -302,6 +302,33 @@ void main() async {
}); });
})); }));
group('toolbar, number list' , (() {
testWidgets('Select Text, Click Toolbar and set style for number list',
(tester) async {
final editor = tester.editor..insertTextNode(singleLineText);
await editor.startTesting();
final numberList = Selection(
start: Position(path: [0],offset: 0),
end: Position(path: [0], offset: singleLineText.length));
await editor.updateSelection(numberList);
await tester.pumpAndSettle(const Duration(milliseconds: 500));
expect(find.byType(ToolbarWidget), findsOneWidget);
final numberListButton = find.byWidgetPredicate((widget) {
if (widget is ToolbarItemWidget) {
return widget.item.id == 'appflowy.toolbar.number_list';
}
return false;
});
expect(numberListButton, findsOneWidget);
await tester.tap(numberListButton);
await tester.pumpAndSettle();
final node = editor.nodeAtPath([0]) as TextNode;
expect(node.subtype, 'number-list');
});
}));
group('toolbar, highlight', (() { group('toolbar, highlight', (() {
testWidgets('Select Text, Click Toolbar and set style for highlighted text', testWidgets('Select Text, Click Toolbar and set style for highlighted text',
(tester) async { (tester) async {

View File

@ -441,4 +441,53 @@ void main() async {
expect(textNode.toPlainText(), text); expect(textNode.toPlainText(), text);
})); }));
}); });
group('Convert single asterisk to italic', () {
testWidgets('Test Single Asterisk for Italics', (tester) async {
const text = '*Hello World';
final editor = tester.editor..insertTextNode(text);
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: text.length),
);
await editor.pressLogicKey(character: '*');
final textNode = editor.nodeAtPath([0]) as TextNode;
final allItalic = textNode.allSatisfyItalicInSelection(
Selection.single(
path: [0],
startOffset: 0,
endOffset: text.length - 1, // delete the first *
),
);
expect(allItalic, true);
});
testWidgets(
'nothing happens if there\'re more than one * precede the current position',
(tester) async {
const text = '**Hello World';
final editor = tester.editor..insertTextNode(text);
await editor.startTesting();
await editor.updateSelection(
Selection.single(path: [0], startOffset: text.length),
);
await editor.pressLogicKey(character: '*');
await tester.pumpAndSettle();
final textNode = editor.nodeAtPath([0]) as TextNode;
final allItalic = textNode.allSatisfyItalicInSelection(
Selection.single(
path: [0],
startOffset: 0,
endOffset: text.length, // insert a new *
),
);
expect(allItalic, false);
});
});
} }

View File

@ -56,6 +56,22 @@ abstract class FlowyColorScheme {
final Color main1; final Color main1;
final Color main2; final Color main2;
final Color shadow; final Color shadow;
final Color sidebarBg;
final Color divider;
final Color topbarBg;
final Color icon;
final Color text;
final Color input;
final Color hint;
final Color primary;
final Color onPrimary;
//page title hover effect
final Color hoverBG1;
//action item hover effect
final Color hoverBG2;
//the text color when it is hovered
final Color hoverFG;
final Color questionBubbleBG;
const FlowyColorScheme({ const FlowyColorScheme({
required this.surface, required this.surface,
@ -87,6 +103,19 @@ abstract class FlowyColorScheme {
required this.main1, required this.main1,
required this.main2, required this.main2,
required this.shadow, required this.shadow,
required this.sidebarBg,
required this.divider,
required this.topbarBg,
required this.icon,
required this.text,
required this.input,
required this.hint,
required this.primary,
required this.onPrimary,
required this.hoverBG1,
required this.hoverBG2,
required this.hoverFG,
required this.questionBubbleBG,
}); });
factory FlowyColorScheme.builtIn(String themeName, Brightness brightness) { factory FlowyColorScheme.builtIn(String themeName, Brightness brightness) {

View File

@ -4,6 +4,21 @@ import 'colorscheme.dart';
const _black = Color(0xff000000); const _black = Color(0xff000000);
const _white = Color(0xFFFFFFFF); const _white = Color(0xFFFFFFFF);
const _lightHover = Color(0xFFe0f8ff);
const _lightSelector = Color(0xfff2fcff);
const _lightBg1 = Color(0xFFFFD13E);
const _lightBg2 = Color(0xffedeef2);
const _lightShader1 = Color(0xff333333);
const _lightShader3 = Color(0xff828282);
const _lightShader6 = Color(0xfff2f2f2);
const _lightMain1 = Color(0xffe21f74);
const _darkShader1 = Color(0xff131720);
const _darkShader2 = Color(0xff1A202C);
const _darkShader3 = Color(0xff363D49);
const _darkShader5 = Color(0xffBBC3CD);
const _darkShader6 = Color(0xffF2F2F2);
const _darkMain1 = Color(0xffe21f74);
class DandelionColorScheme extends FlowyColorScheme { class DandelionColorScheme extends FlowyColorScheme {
const DandelionColorScheme.light() const DandelionColorScheme.light()
@ -20,8 +35,8 @@ class DandelionColorScheme extends FlowyColorScheme {
shader4: const Color(0xffbdbdbd), shader4: const Color(0xffbdbdbd),
shader5: const Color(0xffe0e0e0), shader5: const Color(0xffe0e0e0),
shader6: const Color(0xfff2f2f2), shader6: const Color(0xfff2f2f2),
shader7: const Color(0xffffffff), shader7: _black,
bg1: const Color(0xFFFFD13E), bg1: _lightBg1,
bg2: const Color(0xffedeef2), bg2: const Color(0xffedeef2),
bg3: const Color(0xffe2e4eb), bg3: const Color(0xffe2e4eb),
bg4: const Color(0xff2c144b), bg4: const Color(0xff2c144b),
@ -34,9 +49,22 @@ class DandelionColorScheme extends FlowyColorScheme {
tint7: const Color(0xffddffd6), tint7: const Color(0xffddffd6),
tint8: const Color(0xffdefff1), tint8: const Color(0xffdefff1),
tint9: const Color(0xffe1fbff), tint9: const Color(0xffe1fbff),
main1: const Color(0xffe21f74), main1: _lightMain1,
main2: const Color.fromARGB(255, 224, 25, 111), main2: const Color.fromARGB(255, 224, 25, 111),
shadow: _black, shadow: _black,
sidebarBg: _lightBg1,
divider: _lightShader6,
topbarBg: _white,
icon: _lightShader1,
text: _lightShader1,
input: _white,
hint: _lightShader3,
primary: _lightMain1,
onPrimary: _white,
hoverBG1: _lightBg2,
hoverBG2: _lightHover,
hoverFG: _lightShader1,
questionBubbleBG: _lightSelector,
); );
const DandelionColorScheme.dark() const DandelionColorScheme.dark()
@ -48,12 +76,12 @@ class DandelionColorScheme extends FlowyColorScheme {
yellow: const Color(0xffffd667), yellow: const Color(0xffffd667),
green: const Color(0xff66cf80), green: const Color(0xff66cf80),
shader1: _white, shader1: _white,
shader2: const Color(0xffffffff), shader2: _darkShader2,
shader3: const Color(0xff828282), shader3: const Color(0xff828282),
shader4: const Color(0xffbdbdbd), shader4: const Color(0xffbdbdbd),
shader5: _white, shader5: _darkShader5,
shader6: _black, shader6: _darkShader6,
shader7: _black, shader7: _white,
bg1: const Color(0xFFD5A200), bg1: const Color(0xFFD5A200),
bg2: _black, bg2: _black,
bg3: const Color(0xff4f4f4f), bg3: const Color(0xff4f4f4f),
@ -67,8 +95,21 @@ class DandelionColorScheme extends FlowyColorScheme {
tint7: const Color(0xffbcffad), tint7: const Color(0xffbcffad),
tint8: const Color(0xffadffe2), tint8: const Color(0xffadffe2),
tint9: const Color(0xffade4ff), tint9: const Color(0xffade4ff),
main1: const Color(0xffe21f74), main1: _darkMain1,
main2: const Color.fromARGB(255, 224, 25, 111), main2: const Color.fromARGB(255, 224, 25, 111),
shadow: _black, shadow: _black,
sidebarBg: const Color(0xff232B38),
divider: _darkShader3,
topbarBg: _darkShader1,
icon: _darkShader5,
text: _darkShader5,
input: const Color(0xff282E3A),
hint: _darkShader5,
primary: _darkMain1,
onPrimary: _darkShader1,
hoverBG1: _darkMain1,
hoverBG2: _darkMain1,
hoverFG: _darkShader1,
questionBubbleBG: _darkShader3,
); );
} }

View File

@ -4,25 +4,39 @@ import 'colorscheme.dart';
const _black = Color(0xff000000); const _black = Color(0xff000000);
const _white = Color(0xFFFFFFFF); const _white = Color(0xFFFFFFFF);
const _lightHover = Color(0xFFe0f8ff);
const _lightSelector = Color(0xfff2fcff);
const _lightBg1 = Color(0xfff7f8fc);
const _lightBg2 = Color(0xffedeef2);
const _lightShader1 = Color(0xff333333);
const _lightShader3 = Color(0xff828282);
const _lightShader6 = Color(0xfff2f2f2);
const _lightMain1 = Color(0xff00bcf0);
const _darkShader1 = Color(0xff131720);
const _darkShader2 = Color(0xff1A202C);
const _darkShader3 = Color(0xff363D49);
const _darkShader5 = Color(0xffBBC3CD);
const _darkShader6 = Color(0xffF2F2F2);
const _darkMain1 = Color(0xff00BCF0);
class DefaultColorScheme extends FlowyColorScheme { class DefaultColorScheme extends FlowyColorScheme {
const DefaultColorScheme.light() const DefaultColorScheme.light()
: super( : super(
surface: Colors.white, surface: _white,
hover: const Color(0xFFe0f8ff), hover: _lightHover,
selector: const Color(0xfff2fcff), selector: _lightSelector,
red: const Color(0xfffb006d), red: const Color(0xfffb006d),
yellow: const Color(0xffffd667), yellow: const Color(0xffffd667),
green: const Color(0xff66cf80), green: const Color(0xff66cf80),
shader1: const Color(0xff333333), shader1: _lightShader1,
shader2: const Color(0xff4f4f4f), shader2: const Color(0xff4f4f4f),
shader3: const Color(0xff828282), shader3: _lightShader3,
shader4: const Color(0xffbdbdbd), shader4: const Color(0xffbdbdbd),
shader5: const Color(0xffe0e0e0), shader5: const Color(0xffe0e0e0),
shader6: const Color(0xfff2f2f2), shader6: _lightShader6,
shader7: const Color(0xffffffff), shader7: _lightShader1,
bg1: const Color(0xfff7f8fc), bg1: _lightBg1,
bg2: const Color(0xffedeef2), bg2: _lightBg2,
bg3: const Color(0xffe2e4eb), bg3: const Color(0xffe2e4eb),
bg4: const Color(0xff2c144b), bg4: const Color(0xff2c144b),
tint1: const Color(0xffe8e0ff), tint1: const Color(0xffe8e0ff),
@ -34,41 +48,67 @@ class DefaultColorScheme extends FlowyColorScheme {
tint7: const Color(0xffddffd6), tint7: const Color(0xffddffd6),
tint8: const Color(0xffdefff1), tint8: const Color(0xffdefff1),
tint9: const Color(0xffe1fbff), tint9: const Color(0xffe1fbff),
main1: const Color(0xff00bcf0), main1: _lightMain1,
main2: const Color(0xff00b7ea), main2: const Color(0xff00b7ea),
shadow: _black, shadow: _black,
sidebarBg: _lightBg1,
divider: _lightShader6,
topbarBg: _white,
icon: _lightShader1,
text: _lightShader1,
input: _white,
hint: _lightShader3,
primary: _lightMain1,
onPrimary: _white,
hoverBG1: _lightBg2,
hoverBG2: _lightHover,
hoverFG: _lightShader1,
questionBubbleBG: _lightSelector,
); );
const DefaultColorScheme.dark() const DefaultColorScheme.dark()
: super( : super(
surface: const Color(0xff292929), surface: _darkShader2,
hover: const Color(0xff1f1f1f), hover: _darkMain1,
selector: const Color(0xff333333), selector: _darkShader2,
red: const Color(0xfffb006d), red: const Color(0xfffb006d),
yellow: const Color(0xffffd667), yellow: const Color(0xffF7CF46),
green: const Color(0xff66cf80), green: const Color(0xff66CF80),
shader1: _white, shader1: _darkShader1,
shader2: const Color(0xffffffff), shader2: _darkShader2,
shader3: const Color(0xff828282), shader3: _darkShader3,
shader4: const Color(0xffbdbdbd), shader4: const Color(0xff7C8CA5),
shader5: _white, shader5: _darkShader5,
shader6: _black, shader6: _darkShader6,
shader7: _black, shader7: _white,
bg1: _black, bg1: const Color(0xffF7F8FC),
bg2: _black, bg2: const Color(0xffEDEEF2),
bg3: const Color(0xff4f4f4f), bg3: _darkMain1,
bg4: const Color(0xff2c144b), bg4: const Color(0xff2C144B),
tint1: const Color(0xffc3adff), tint1: const Color(0xff8738F5),
tint2: const Color(0xffffadf9), tint2: const Color(0xffE6336E),
tint3: const Color(0xffffadad), tint3: const Color(0xffFF2D9E),
tint4: const Color(0xffffcfad), tint4: const Color(0xffE9973E),
tint5: const Color(0xfffffead), tint5: const Color(0xffFBF000),
tint6: const Color(0xffe6ffa3), tint6: const Color(0xffC0F000),
tint7: const Color(0xffbcffad), tint7: const Color(0xff15F74E),
tint8: const Color(0xffadffe2), tint8: const Color(0xff00F0E2),
tint9: const Color(0xffade4ff), tint9: const Color(0xff00BCF0),
main1: const Color(0xff00bcf0), main1: _darkMain1,
main2: const Color(0xff009cc7), main2: const Color(0xff00B7EA),
shadow: _black, shadow: const Color(0xff0F131C),
sidebarBg: const Color(0xff232B38),
divider: _darkShader3,
topbarBg: _darkShader1,
icon: _darkShader5,
text: _darkShader5,
input: const Color(0xff282E3A),
hint: _darkShader5,
primary: _darkMain1,
onPrimary: _darkShader1,
hoverBG1: _darkMain1,
hoverBG2: _darkMain1,
hoverFG: _darkShader1,
questionBubbleBG: _darkShader3,
); );
} }

View File

@ -5,6 +5,22 @@ import 'colorscheme.dart';
const _black = Color(0xff000000); const _black = Color(0xff000000);
const _white = Color(0xFFFFFFFF); const _white = Color(0xFFFFFFFF);
const _lightHover = Color(0xFFe0f8ff);
const _lightSelector = Color(0xfff2fcff);
const _lightBg1 = Color(0xfff7f8fc);
const _lightBg2 = Color(0xffedeef2);
const _lightShader1 = Color(0xff333333);
const _lightShader3 = Color(0xff828282);
const _lightShader6 = Color(0xfff2f2f2);
const _lightMain1 = Color(0xffA652FB);
const _darkShader1 = Color(0xff131720);
const _darkShader2 = Color(0xff1A202C);
const _darkShader3 = Color(0xff363D49);
const _darkShader5 = Color(0xffBBC3CD);
const _darkShader6 = Color(0xffF2F2F2);
const _darkMain1 = Color(0xffA652FB);
class LavenderColorScheme extends FlowyColorScheme { class LavenderColorScheme extends FlowyColorScheme {
const LavenderColorScheme.light() const LavenderColorScheme.light()
: super( : super(
@ -20,7 +36,7 @@ class LavenderColorScheme extends FlowyColorScheme {
shader4: const Color(0xffbdbdbd), shader4: const Color(0xffbdbdbd),
shader5: const Color(0xffe0e0e0), shader5: const Color(0xffe0e0e0),
shader6: const Color(0xfff2f2f2), shader6: const Color(0xfff2f2f2),
shader7: const Color(0xffffffff), shader7: _black,
bg1: const Color(0xffAC59FF), bg1: const Color(0xffAC59FF),
bg2: const Color(0xffedeef2), bg2: const Color(0xffedeef2),
bg3: const Color(0xffe2e4eb), bg3: const Color(0xffe2e4eb),
@ -34,9 +50,22 @@ class LavenderColorScheme extends FlowyColorScheme {
tint7: const Color(0xffddffd6), tint7: const Color(0xffddffd6),
tint8: const Color(0xffdefff1), tint8: const Color(0xffdefff1),
tint9: const Color(0xffe1fbff), tint9: const Color(0xffe1fbff),
main1: const Color(0xffA652FB), main1: _lightMain1,
main2: const Color(0xff9327FF), main2: const Color(0xff9327FF),
shadow: _black, shadow: _black,
sidebarBg: _lightBg1,
divider: _lightShader6,
topbarBg: _white,
icon: _lightShader1,
text: _lightShader1,
input: _white,
hint: _lightShader3,
primary: _lightMain1,
onPrimary: _white,
hoverBG1: _lightBg2,
hoverBG2: _lightHover,
hoverFG: _lightShader1,
questionBubbleBG: _lightSelector,
); );
const LavenderColorScheme.dark() const LavenderColorScheme.dark()
@ -48,12 +77,12 @@ class LavenderColorScheme extends FlowyColorScheme {
yellow: const Color(0xffffd667), yellow: const Color(0xffffd667),
green: const Color(0xff66cf80), green: const Color(0xff66cf80),
shader1: _white, shader1: _white,
shader2: const Color(0xffffffff), shader2: _darkShader2,
shader3: const Color(0xff828282), shader3: const Color(0xff828282),
shader4: const Color(0xffbdbdbd), shader4: const Color(0xffbdbdbd),
shader5: _white, shader5: _white,
shader6: _black, shader6: _darkShader6,
shader7: _black, shader7: _white,
bg1: const Color(0xff8C23F6), bg1: const Color(0xff8C23F6),
bg2: _black, bg2: _black,
bg3: const Color(0xff4f4f4f), bg3: const Color(0xff4f4f4f),
@ -67,8 +96,21 @@ class LavenderColorScheme extends FlowyColorScheme {
tint7: const Color(0xffbcffad), tint7: const Color(0xffbcffad),
tint8: const Color(0xffadffe2), tint8: const Color(0xffadffe2),
tint9: const Color(0xffade4ff), tint9: const Color(0xffade4ff),
main1: const Color(0xffA652FB), main1: _darkMain1,
main2: const Color(0xff9327FF), main2: const Color(0xff9327FF),
shadow: _black, shadow: _black,
sidebarBg: const Color(0xff232B38),
divider: _darkShader3,
topbarBg: _darkShader1,
icon: _darkShader5,
text: _darkShader5,
input: const Color(0xff282E3A),
hint: _darkShader5,
primary: _darkMain1,
onPrimary: _darkShader1,
hoverBG1: _darkMain1,
hoverBG2: _darkMain1,
hoverFG: _darkShader1,
questionBubbleBG: _darkShader3,
); );
} }

View File

@ -1,6 +1,30 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter/material.dart';
/// For icon that needs to change color when it is on hovered
///
/// Get the hover color from ThemeData
class FlowySvg extends StatelessWidget {
const FlowySvg({super.key, this.size, required this.name});
final String name;
final Size? size;
@override
Widget build(BuildContext context) {
if (size != null) {
return SizedBox.fromSize(
size: size,
child: SvgPicture.asset('assets/images/$name.svg',
color: Theme.of(context).iconTheme.color),
);
} else {
return SvgPicture.asset('assets/images/$name.svg',
color: Theme.of(context).iconTheme.color);
}
}
}
Widget svgWidget(String name, {Size? size, Color? color}) { Widget svgWidget(String name, {Size? size, Color? color}) {
if (size != null) { if (size != null) {
return SizedBox.fromSize( return SizedBox.fromSize(

View File

@ -6,7 +6,14 @@ String languageFromLocale(Locale locale) {
case "en": case "en":
return "English"; return "English";
case "zh": case "zh":
return "简体中文"; switch (locale.countryCode) {
case "CN":
return "简体中文";
case "TW":
return "繁體中文";
default:
return locale.languageCode;
}
// Then in alphabetical order // Then in alphabetical order
case "ca": case "ca":

View File

@ -81,7 +81,7 @@ class _PopoverContainer extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final decoration = this.decoration ?? final decoration = this.decoration ??
FlowyDecoration.decoration( FlowyDecoration.decoration(
Theme.of(context).colorScheme.surface, Theme.of(context).cardColor,
Theme.of(context).colorScheme.shadow.withOpacity(0.15), Theme.of(context).colorScheme.shadow.withOpacity(0.15),
); );

View File

@ -26,6 +26,7 @@ class FlowyDialog extends StatelessWidget {
final size = windowSize * 0.7; final size = windowSize * 0.7;
return SimpleDialog( return SimpleDialog(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
backgroundColor: Theme.of(context).cardColor,
title: title, title: title,
shape: shape ?? shape: shape ??
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),

View File

@ -1,11 +1,9 @@
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/ignore_parent_gesture.dart'; import 'package:flowy_infra_ui/widget/ignore_parent_gesture.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:textstyle_extensions/textstyle_extensions.dart';
class FlowyButton extends StatelessWidget { class FlowyButton extends StatelessWidget {
final Widget text; final Widget text;
@ -177,7 +175,8 @@ class FlowyTextButton extends StatelessWidget {
highlightElevation: 0, highlightElevation: 0,
shape: RoundedRectangleBorder(borderRadius: radius ?? Corners.s6Border), shape: RoundedRectangleBorder(borderRadius: radius ?? Corners.s6Border),
fillColor: fillColor ?? Theme.of(context).colorScheme.secondaryContainer, fillColor: fillColor ?? Theme.of(context).colorScheme.secondaryContainer,
hoverColor: hoverColor ?? Theme.of(context).colorScheme.secondary, hoverColor:
hoverColor ?? Theme.of(context).colorScheme.secondaryContainer,
focusColor: Colors.transparent, focusColor: Colors.transparent,
splashColor: Colors.transparent, splashColor: Colors.transparent,
highlightColor: Colors.transparent, highlightColor: Colors.transparent,
@ -195,7 +194,6 @@ class FlowyTextButton extends StatelessWidget {
if (tooltip != null) { if (tooltip != null) {
child = Tooltip( child = Tooltip(
message: tooltip!, message: tooltip!,
textStyle: AFThemeExtension.of(context).caption.textColor(Colors.white),
child: child, child: child,
); );
} }
@ -285,7 +283,6 @@ class FlowyRichTextButton extends StatelessWidget {
if (tooltip != null) { if (tooltip != null) {
child = Tooltip( child = Tooltip(
message: tooltip!, message: tooltip!,
textStyle: AFThemeExtension.of(context).caption.textColor(Colors.white),
child: child, child: child,
); );
} }

View File

@ -115,11 +115,11 @@ class HoverStyle {
class FlowyHoverContainer extends StatelessWidget { class FlowyHoverContainer extends StatelessWidget {
final HoverStyle style; final HoverStyle style;
final Widget? child; final Widget child;
const FlowyHoverContainer({ const FlowyHoverContainer({
Key? key, Key? key,
this.child, required this.child,
required this.style, required this.style,
}) : super(key: key); }) : super(key: key);
@ -137,7 +137,22 @@ class FlowyHoverContainer extends StatelessWidget {
color: style.hoverColor ?? Theme.of(context).colorScheme.secondary, color: style.hoverColor ?? Theme.of(context).colorScheme.secondary,
borderRadius: style.borderRadius, borderRadius: style.borderRadius,
), ),
child: child, child:
//override text's theme with new color when it is hovered
Theme(
data: Theme.of(context).copyWith(
textTheme: Theme.of(context).textTheme.copyWith(
bodyMedium: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(color: Theme.of(context).colorScheme.onSurface),
),
iconTheme: Theme.of(context)
.iconTheme
.copyWith(color: Theme.of(context).colorScheme.onSurface),
),
child: child,
),
); );
} }
} }

View File

@ -9,7 +9,7 @@ class BaseStyledButton extends StatefulWidget {
final Color? bgColor; final Color? bgColor;
final Color? focusColor; final Color? focusColor;
final Color? hoverColor; final Color? hoverColor;
final Color? downColor; final Color? highlightColor;
final EdgeInsets? contentPadding; final EdgeInsets? contentPadding;
final double? minWidth; final double? minWidth;
final double? minHeight; final double? minHeight;
@ -34,7 +34,7 @@ class BaseStyledButton extends StatefulWidget {
this.minHeight, this.minHeight,
this.borderRadius, this.borderRadius,
this.hoverColor, this.hoverColor,
this.downColor, this.highlightColor,
this.shape, this.shape,
this.useBtnText = true, this.useBtnText = true,
this.autoFocus = false, this.autoFocus = false,
@ -116,10 +116,8 @@ class BaseStyledBtnState extends State<BaseStyledButton> {
highlightElevation: 0, highlightElevation: 0,
focusElevation: 0, focusElevation: 0,
fillColor: Colors.transparent, fillColor: Colors.transparent,
hoverColor: hoverColor: widget.hoverColor ?? Colors.transparent,
widget.hoverColor ?? Theme.of(context).colorScheme.secondary, highlightColor: widget.highlightColor ?? Colors.transparent,
highlightColor:
widget.downColor ?? Theme.of(context).colorScheme.primary,
focusColor: widget.focusColor ?? Colors.grey.withOpacity(0.35), focusColor: widget.focusColor ?? Colors.grey.withOpacity(0.35),
constraints: BoxConstraints( constraints: BoxConstraints(
minHeight: widget.minHeight ?? 0, minWidth: widget.minWidth ?? 0), minHeight: widget.minHeight ?? 0, minWidth: widget.minWidth ?? 0),

View File

@ -42,7 +42,6 @@ class PrimaryButton extends StatelessWidget {
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
bgColor: Theme.of(context).colorScheme.primary, bgColor: Theme.of(context).colorScheme.primary,
hoverColor: Theme.of(context).colorScheme.primaryContainer, hoverColor: Theme.of(context).colorScheme.primaryContainer,
downColor: Theme.of(context).colorScheme.primary,
borderRadius: bigMode ? Corners.s12Border : Corners.s8Border, borderRadius: bigMode ? Corners.s12Border : Corners.s8Border,
onPressed: onPressed, onPressed: onPressed,
child: child, child: child,

View File

@ -42,8 +42,6 @@ class SecondaryButton extends StatelessWidget {
minHeight: bigMode ? 40 : 38, minHeight: bigMode ? 40 : 38,
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
bgColor: Theme.of(context).colorScheme.surface, bgColor: Theme.of(context).colorScheme.surface,
hoverColor: Theme.of(context).colorScheme.secondary,
downColor: Theme.of(context).colorScheme.primary,
outlineColor: Theme.of(context).colorScheme.primary, outlineColor: Theme.of(context).colorScheme.primary,
borderRadius: bigMode ? Corners.s12Border : Corners.s8Border, borderRadius: bigMode ? Corners.s12Border : Corners.s8Border,
onPressed: onPressed, onPressed: onPressed,

View File

@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.1.1 version: 0.1.2
environment: environment:
sdk: ">=2.18.0 <3.0.0" sdk: ">=2.18.0 <3.0.0"
@ -89,7 +89,6 @@ dependencies:
google_fonts: ^3.0.1 google_fonts: ^3.0.1
file_picker: <=5.0.0 file_picker: <=5.0.0
percent_indicator: ^4.0.1 percent_indicator: ^4.0.1
appflowy_editor_plugins: appflowy_editor_plugins:
path: packages/appflowy_editor_plugins path: packages/appflowy_editor_plugins
calendar_view: ^1.0.1 calendar_view: ^1.0.1

View File

@ -10,7 +10,7 @@ pub fn init_flowy_core() -> AppFlowyCore {
} }
data_path.push("data"); data_path.push("data");
std::env::set_var("RUST_LOG", "debug"); std::env::set_var("RUST_LOG", "trace");
let server_config = get_client_server_configuration().unwrap(); let server_config = get_client_server_configuration().unwrap();
let config = AppFlowyCoreConfig::new( let config = AppFlowyCoreConfig::new(
data_path.to_str().unwrap(), data_path.to_str().unwrap(),

View File

@ -10,6 +10,8 @@ import { ClockSvg } from '$app/components/_shared/svg/ClockSvg';
import { MoreSvg } from '$app/components/_shared/svg/MoreSvg'; import { MoreSvg } from '$app/components/_shared/svg/MoreSvg';
import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg'; import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg';
import { useCell } from '$app/components/_shared/database-hooks/useCell'; import { useCell } from '$app/components/_shared/database-hooks/useCell';
import { CalendarData } from '$app/stores/effects/database/cell/controller_builder';
import { DateCellDataPB } from '@/services/backend';
export const DatePickerPopup = ({ export const DatePickerPopup = ({
left, left,
@ -29,7 +31,6 @@ export const DatePickerPopup = ({
const { data, cellController } = useCell(cellIdentifier, cellCache, fieldController); const { data, cellController } = useCell(cellIdentifier, cellCache, fieldController);
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const [adjustedTop, setAdjustedTop] = useState(-100); const [adjustedTop, setAdjustedTop] = useState(-100);
// const [value, setValue] = useState();
const { t } = useTranslation(''); const { t } = useTranslation('');
const [selectedDate, setSelectedDate] = useState<Date>(new Date()); const [selectedDate, setSelectedDate] = useState<Date>(new Date());
@ -48,15 +49,18 @@ export const DatePickerPopup = ({
}); });
useEffect(() => { useEffect(() => {
// console.log((data as DateCellDataPB).date); const date_pb = data as DateCellDataPB | undefined;
// setSelectedDate(new Date((data as DateCellDataPB).date)); if (!date_pb || !date_pb?.date.length) return;
// should be changed after we can modify date format
setSelectedDate(dayjs(date_pb.date, 'MMM DD, YYYY').toDate());
}, [data]); }, [data]);
const onChange = (v: Date | null | (Date | null)[]) => { const onChange = async (v: Date | null | (Date | null)[]) => {
if (v instanceof Date) { if (v instanceof Date) {
console.log(dayjs(v).format('YYYY-MM-DD'));
setSelectedDate(v); setSelectedDate(v);
// void cellController?.saveCellData(new DateCellDataPB({ date: dayjs(v).format('YYYY-MM-DD') })); const date = new CalendarData(dayjs(v).add(dayjs().utcOffset(), 'minutes').toDate(), false);
await cellController?.saveCellData(date);
} }
}; };

View File

@ -76,7 +76,10 @@ export const EditCellWrapper = ({
)} )}
{cellIdentifier.fieldType === FieldType.Checkbox && cellController && ( {cellIdentifier.fieldType === FieldType.Checkbox && cellController && (
<EditCheckboxCell data={data as boolean | undefined} cellController={cellController}></EditCheckboxCell> <EditCheckboxCell
data={data as 'Yes' | 'No' | undefined}
cellController={cellController}
></EditCheckboxCell>
)} )}
{cellIdentifier.fieldType === FieldType.DateTime && ( {cellIdentifier.fieldType === FieldType.DateTime && (

View File

@ -1,22 +1,26 @@
import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg'; import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg';
import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg'; import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg';
import { CellController } from '$app/stores/effects/database/cell/cell_controller'; import { CheckboxCellController } from '$app/stores/effects/database/cell/controller_builder';
export const EditCheckboxCell = ({ export const EditCheckboxCell = ({
data, data,
cellController, cellController,
}: { }: {
data: boolean | undefined; data: 'Yes' | 'No' | undefined;
cellController: CellController<any, any>; cellController: CheckboxCellController;
}) => { }) => {
const toggleValue = async () => { const toggleValue = async () => {
await cellController?.saveCellData(!data); if (data === 'Yes') {
await cellController?.saveCellData('No');
} else {
await cellController?.saveCellData('Yes');
}
}; };
return ( return (
<div onClick={() => toggleValue()} className={'block px-4 py-2'}> <div onClick={() => toggleValue()} className={'block px-4 py-2'}>
<button className={'h-5 w-5'}> <button className={'h-5 w-5'}>
{data ? <EditorCheckSvg></EditorCheckSvg> : <EditorUncheckSvg></EditorUncheckSvg>} {data === 'Yes' ? <EditorCheckSvg></EditorCheckSvg> : <EditorUncheckSvg></EditorUncheckSvg>}
</button> </button>
</div> </div>
); );

View File

@ -108,7 +108,11 @@ export const EditRow = ({
const onDragEnd: OnDragEndResponder = (result) => { const onDragEnd: OnDragEndResponder = (result) => {
if (!result.destination?.index) return; if (!result.destination?.index) return;
void controller.moveField(result.source.droppableId, result.source.index, result.destination.index); void controller.moveField({
fieldId: result.source.droppableId,
fromIndex: result.source.index,
toIndex: result.destination.index,
});
}; };
return ( return (

View File

@ -1,13 +1,12 @@
import { CellIdentifier } from '../../stores/effects/database/cell/cell_bd_svc'; import { CellIdentifier } from '../../stores/effects/database/cell/cell_bd_svc';
import { CellCache } from '../../stores/effects/database/cell/cell_cache'; import { CellCache } from '../../stores/effects/database/cell/cell_cache';
import { FieldController } from '../../stores/effects/database/field/field_controller'; import { FieldController } from '../../stores/effects/database/field/field_controller';
import { FieldType, SelectOptionCellDataPB } from '../../../services/backend'; import { FieldType } from '../../../services/backend';
import { BoardOptionsCell } from './BoardOptionsCell'; import { BoardOptionsCell } from './BoardOptionsCell';
import { BoardDateCell } from './BoardDateCell'; import { BoardDateCell } from './BoardDateCell';
import { BoardTextCell } from './BoardTextCell'; import { BoardTextCell } from './BoardTextCell';
import { BoardUrlCell } from '$app/components/board/BoardUrlCell'; import { BoardUrlCell } from '$app/components/board/BoardUrlCell';
import { useCell } from '../_shared/database-hooks/useCell'; import { BoardCheckboxCell } from '$app/components/board/BoardCheckboxCell';
import { CellOptions } from '../_shared/EditRow/CellOptions';
export const BoardCell = ({ export const BoardCell = ({
cellIdentifier, cellIdentifier,
@ -18,19 +17,16 @@ export const BoardCell = ({
cellCache: CellCache; cellCache: CellCache;
fieldController: FieldController; fieldController: FieldController;
}) => { }) => {
const { data, cellController } = useCell(cellIdentifier, cellCache, fieldController);
return ( return (
<> <>
{cellIdentifier.fieldType === FieldType.SingleSelect || {cellIdentifier.fieldType === FieldType.SingleSelect ||
cellIdentifier.fieldType === FieldType.MultiSelect || cellIdentifier.fieldType === FieldType.MultiSelect ||
cellIdentifier.fieldType === FieldType.Checklist ? ( cellIdentifier.fieldType === FieldType.Checklist ? (
<CellOptions <BoardOptionsCell
data={data as SelectOptionCellDataPB} cellIdentifier={cellIdentifier}
onEditClick={(top: number, left: number) => { cellCache={cellCache}
console.log(top, left); fieldController={fieldController}
}} ></BoardOptionsCell>
/>
) : cellIdentifier.fieldType === FieldType.DateTime ? ( ) : cellIdentifier.fieldType === FieldType.DateTime ? (
<BoardDateCell <BoardDateCell
cellIdentifier={cellIdentifier} cellIdentifier={cellIdentifier}
@ -43,6 +39,12 @@ export const BoardCell = ({
cellCache={cellCache} cellCache={cellCache}
fieldController={fieldController} fieldController={fieldController}
></BoardUrlCell> ></BoardUrlCell>
) : cellIdentifier.fieldType === FieldType.Checkbox ? (
<BoardCheckboxCell
cellIdentifier={cellIdentifier}
cellCache={cellCache}
fieldController={fieldController}
></BoardCheckboxCell>
) : ( ) : (
<BoardTextCell <BoardTextCell
cellIdentifier={cellIdentifier} cellIdentifier={cellIdentifier}

View File

@ -0,0 +1,23 @@
import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg';
import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg';
import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
import { FieldController } from '$app/stores/effects/database/field/field_controller';
import { useCell } from '$app/components/_shared/database-hooks/useCell';
export const BoardCheckboxCell = ({
cellIdentifier,
cellCache,
fieldController,
}: {
cellIdentifier: CellIdentifier;
cellCache: CellCache;
fieldController: FieldController;
}) => {
const { data } = useCell(cellIdentifier, cellCache, fieldController);
return (
<i className={'h-5 w-5'}>
{data === 'Yes' ? <EditorCheckSvg></EditorCheckSvg> : <EditorUncheckSvg></EditorUncheckSvg>}
</i>
);
};

View File

@ -12,6 +12,7 @@ import { RowInfo } from '../../stores/effects/database/row/row_cache';
import { RowController } from '../../stores/effects/database/row/row_controller'; import { RowController } from '../../stores/effects/database/row/row_controller';
import { import {
CellControllerBuilder, CellControllerBuilder,
CheckboxCellController,
DateCellController, DateCellController,
NumberCellController, NumberCellController,
SelectOptionCellController, SelectOptionCellController,
@ -126,6 +127,17 @@ export async function makeDateCellController(
return Some(builder.build() as DateCellController); return Some(builder.build() as DateCellController);
} }
export async function makeCheckboxCellController(
fieldId: string,
rowInfo: RowInfo,
databaseController: DatabaseController
): Promise<Option<CheckboxCellController>> {
const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.Checkbox, databaseController).then(
(result) => result.unwrap()
);
return Some(builder.build() as CheckboxCellController);
}
export async function makeURLCellController( export async function makeURLCellController(
fieldId: string, fieldId: string,
rowInfo: RowInfo, rowInfo: RowInfo,

View File

@ -8,10 +8,13 @@ import {
TestDeleteField, TestDeleteField,
TestDeleteRow, TestDeleteRow,
TestEditCell, TestEditCell,
TestEditCheckboxCell,
TestEditDateCell,
TestEditField, TestEditField,
TestEditTextCell, TestEditTextCell,
TestEditURLCell, TestEditURLCell,
TestGetSingleSelectFieldData, TestGetSingleSelectFieldData,
TestMoveField,
TestSwitchFromMultiSelectToText, TestSwitchFromMultiSelectToText,
TestSwitchFromSingleSelectToNumber, TestSwitchFromSingleSelectToNumber,
} from './TestGrid'; } from './TestGrid';
@ -37,9 +40,12 @@ export const TestAPI = () => {
<TestEditCell></TestEditCell> <TestEditCell></TestEditCell>
<TestEditTextCell></TestEditTextCell> <TestEditTextCell></TestEditTextCell>
<TestEditURLCell></TestEditURLCell> <TestEditURLCell></TestEditURLCell>
<TestEditDateCell></TestEditDateCell>
<TestEditCheckboxCell></TestEditCheckboxCell>
<TestCreateSelectOptionInCell></TestCreateSelectOptionInCell> <TestCreateSelectOptionInCell></TestCreateSelectOptionInCell>
<TestGetSingleSelectFieldData></TestGetSingleSelectFieldData> <TestGetSingleSelectFieldData></TestGetSingleSelectFieldData>
<TestEditField></TestEditField> <TestEditField></TestEditField>
<TestMoveField></TestMoveField>
<TestCreateNewField></TestCreateNewField> <TestCreateNewField></TestCreateNewField>
<TestDeleteField></TestDeleteField> <TestDeleteField></TestDeleteField>
<TestSwitchFromSingleSelectToNumber></TestSwitchFromSingleSelectToNumber> <TestSwitchFromSingleSelectToNumber></TestSwitchFromSingleSelectToNumber>

Some files were not shown because too many files have changed in this diff Show More