昨天我們依照JSON把Flex Message刻了出來,真心覺得應該可以有一個Generate Code的工具,把用Flex Message Simulator產生出來的JSON轉成對應的程式碼,這樣開發應該可以方便很多QQ。
言歸正傳,雖然昨天刻好了Flex Message的程式碼,但是各個欄位顯示什麼都還是寫死的,我們今天就來把各個區塊調整&封裝一下,讓我們能更有彈性&動態的組合出需要的Flex Message。
首先我們把組合的工作移到Domain層來處理,在domain/drive
下新增flex.go
接著我們仔細看一下圖片,來拆解&分析一下我們Flex Message的格式
根據上面的分析,我們可以先寫出要組成bubble會需要的4個區塊,讓他們都回傳[]linebot.FlexComponent
,等等再組起來就好。
// internal\domain\drive\flex.go
// Title區塊
func folderTitleFlexComponents(folderType string, name string, path string) []linebot.FlexComponent {}
// Folder區塊,folderM是 map[folderID]:folderName
func folderFlexComponents(folderM map[string]string) []linebot.FlexComponent {}
// Files區塊,fileM 是 map[fileID]:fileName
func fileFlexComponents(fileM map[string]string) []linebot.FlexComponent {}
// Button區塊,讓他能回傳當前資料夾ID
func buttonFlexComponents(currentFolderID string) []linebot.FlexComponent {}
接著我們來一一實現,從Title區塊開始,這邊比較單純,只要讓外部傳入的參數對應到Text的部分就好。
func folderTitleFlexComponents(folderType string, name string, path string) []linebot.FlexComponent {
var title []linebot.FlexComponent
title = append(title,
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: folderType,
Weight: linebot.FlexTextWeightTypeBold,
Color: "#1DB446",
Size: linebot.FlexTextSizeTypeSm,
},
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: name,
Weight: linebot.FlexTextWeightTypeBold,
Size: linebot.FlexTextSizeTypeXxl,
Margin: linebot.FlexComponentMarginTypeMd,
},
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: path,
Size: linebot.FlexTextSizeTypeXs,
Color: "#aaaaaa",
Wrap: true,
},
&linebot.SeparatorComponent{
Type: linebot.FlexComponentTypeSeparator,
Margin: linebot.FlexComponentMarginTypeXxl,
})
return title
}
Folder區塊,我們假設傳入一個folderM
是子資料夾的ID與名稱對應的Map,如果map為空代表該資料夾下,沒有其他的子資料夾,我們就做一個”無”的TextComponent回傳。
如果map不為空,我們要遍歷整個folderM
,取出folderID
跟folderName
來製作每顯示一行需要的三個對應的元件(Text+Filler+Button)。
folderID
,並且用action
來代表對資料夾執行的動作。func folderFlexComponents(folderM map[string]string) []linebot.FlexComponent {
var folders []linebot.FlexComponent
var folderFlex []linebot.FlexComponent
// map為空
if len(folderM) == 0 {
folderFlex = append(folderFlex,
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeVertical,
Margin: linebot.FlexComponentMarginTypeXxl,
Spacing: linebot.FlexComponentSpacingTypeSm,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "無",
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
Decoration: linebot.FlexTextDecorationTypeNone,
MaxLines: linebot.IntPtr(25),
Align: linebot.FlexComponentAlignTypeStart,
Margin: linebot.FlexComponentMarginTypeNone,
Gravity: linebot.FlexComponentGravityTypeCenter,
Flex: linebot.IntPtr(0),
},
},
},
// Separator
&linebot.SeparatorComponent{
Margin: linebot.FlexComponentMarginTypeXxl,
},
)
return folderFlex
}
// map不為空
for folderID, folderName := range folderM {
folders = append(folders, &linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: folderName,
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
Decoration: linebot.FlexTextDecorationTypeUnderline,
MaxLines: linebot.IntPtr(25),
Align: linebot.FlexComponentAlignTypeStart,
Margin: linebot.FlexComponentMarginTypeNone,
Gravity: linebot.FlexComponentGravityTypeCenter,
Flex: linebot.IntPtr(0),
},
&linebot.FillerComponent{
Type: linebot.FlexComponentTypeFiller,
},
&linebot.ButtonComponent{
Type: linebot.FlexComponentTypeButton,
Action: &linebot.PostbackAction{
Label: "進入資料夾",
Data: "action=openFolder&folderID=" + folderID,
DisplayText: "進入" + folderName,
},
Style: linebot.FlexButtonStyleTypeLink,
Height: linebot.FlexButtonHeightTypeSm,
Gravity: linebot.FlexComponentGravityTypeCenter,
Flex: linebot.IntPtr(0),
AdjustMode: linebot.FlexComponentAdjustModeTypeShrinkToFit,
},
},
})
}
folderFlex = append(folderFlex,
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeVertical,
Margin: linebot.FlexComponentMarginTypeXxl,
Spacing: linebot.FlexComponentSpacingTypeSm,
Contents: folders,
},
// Separator
&linebot.SeparatorComponent{
Margin: linebot.FlexComponentMarginTypeXxl,
},
)
return folderFlex
}
Files區塊,跟folderM
做法一樣,只是傳入的是檔案ID與名稱組合的Map。透過len(fileM)
來製作Total Files的部分,然後一樣遍歷fileM
用每一個取到的檔案名稱製作對應的TextComponent
。
func fileFlexComponents(fileM map[string]string) []linebot.FlexComponent {
totalFiles := len(fileM)
fileFlex := []linebot.FlexComponent{
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Margin: linebot.FlexComponentMarginTypeXxl,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "Total Files",
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
Flex: linebot.IntPtr(0),
},
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
// Insert totalFiles
Text: strconv.Itoa(totalFiles),
Size: linebot.FlexTextSizeTypeSm,
Color: "#111111",
Align: linebot.FlexComponentAlignTypeEnd,
},
},
},
}
// Generate files
var files []linebot.FlexComponent
for _, name := range fileM {
files = append(files,
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: name,
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
},
)
}
fileFlex = append(fileFlex, files...)
// Add Separator
fileFlex = append(fileFlex,
&linebot.SeparatorComponent{
Margin: linebot.FlexComponentMarginTypeXxl,
},
)
return fileFlex
}
Button區塊,這邊我們將action=setFolder
,代表設定當前資料夾為上傳資料夾。之後再處理Button的PostbackAction時,我們也是靠action
帶的動作,來認定是哪個按鈕被按下,並進行對應的後續處理。
func buttonFlexComponents(currentFolderID string) []linebot.FlexComponent {
var buttonFlex []linebot.FlexComponent
buttonFlex = append(buttonFlex,
// Button
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Margin: linebot.FlexComponentMarginTypeMd,
Contents: []linebot.FlexComponent{
&linebot.ButtonComponent{
Type: linebot.FlexComponentTypeButton,
Action: &linebot.PostbackAction{
Label: "設為上傳資料夾",
Data: "action=setFolder&folderID=" + currentFolderID,
DisplayText: "設為上傳資料夾",
},
Style: linebot.FlexButtonStyleTypePrimary,
AdjustMode: linebot.FlexComponentAdjustModeTypeShrinkToFit,
},
},
})
return buttonFlex
}
到這裡我們完成了組成單一個Bubble需要的4個區塊,那我們今天就先寫到這,明天透過這4個區塊,把Bubble跟Carousel組合起來,就可以提供給Service調用了,那我們明天見囉~