iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0

昨天我們依照JSON把Flex Message刻了出來,真心覺得應該可以有一個Generate Code的工具,把用Flex Message Simulator產生出來的JSON轉成對應的程式碼,這樣開發應該可以方便很多QQ。

言歸正傳,雖然昨天刻好了Flex Message的程式碼,但是各個欄位顯示什麼都還是寫死的,我們今天就來把各個區塊調整&封裝一下,讓我們能更有彈性&動態的組合出需要的Flex Message。

  1. 首先我們把組合的工作移到Domain層來處理,在domain/drive下新增flex.go

  2. 接著我們仔細看一下圖片,來拆解&分析一下我們Flex Message的格式
    https://ithelp.ithome.com.tw/upload/images/20231012/201159907CGTuK0l0j.png

    • Carousel由數個Bubble組成
      • 每一個Bubble都代表當前目錄下的一個資料夾,一個Bubble又可以拆成4個區塊
        • Title區塊: 顯示當前資料夾類別(MyDrive or SharedWithMe)、資料夾名稱、當前路徑
        • Folder區塊: 顯示子資料夾名稱、一個進入資料夾的按鈕
        • Files區塊: 顯示總檔案數、檔案名稱
        • Button區塊: 一個設定為上傳資料夾的按鈕
  3. 根據上面的分析,我們可以先寫出要組成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 {}
    
  4. 接著我們來一一實現,從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
    }
    
  5. Folder區塊,我們假設傳入一個folderM是子資料夾的ID與名稱對應的Map,如果map為空代表該資料夾下,沒有其他的子資料夾,我們就做一個”無”的TextComponent回傳。

    如果map不為空,我們要遍歷整個folderM,取出folderIDfolderName來製作每顯示一行需要的三個對應的元件(Text+Filler+Button)。

    • Text: 代入folderName,顯示子資料夾名稱
    • Filler: 單純空格排版用
    • Button: 這邊Label代表按鈕顯示的文字,DisplayText代表使用者按下按鈕後,會顯示傳送給LineBot的文字,Data是藏在背後傳給LineBot的值,我們可以用url帶參數的形式來傳遞值,之後只要解析出來就好。我們的兩種按鈕目前只會操作到資料夾,所以我們的參數會帶上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
    
    }
    
  6. 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
    }
    
  7. 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調用了,那我們明天見囉~


上一篇
Day26 加上Flex Message Carousel
下一篇
Day28 用Go動態組合Flex Message 02
系列文
Golang LineBot X GoogleDrive:LINE有各種限制!? 那就丟上Drive吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言