Bläddra i källkod

1.优化商品列表加载方式

2.优化自定义背景色向上推出界面
tags/0.0.4
“yanghuaxuan” 3 år sedan
förälder
incheckning
4e82fc7a17
11 ändrade filer med 190 tillägg och 99 borttagningar
  1. +27
    -27
      example/android/app/build.gradle
  2. +6
    -3
      lib/dialog/global_dialog/intellect_search_goods_dialog/intellect_create.dart
  3. +9
    -0
      lib/pages/custom_page/bloc/background_bloc.dart
  4. +15
    -4
      lib/pages/custom_page/bloc/custom_page_repository.dart
  5. +20
    -14
      lib/pages/custom_page/custom_item_page.dart
  6. +69
    -27
      lib/pages/custom_page/custom_page.dart
  7. +14
    -14
      lib/register.dart
  8. +2
    -0
      lib/widgets/home/home_goods/bloc/home_goods_header_bloc.dart
  9. +19
    -5
      lib/widgets/home/home_goods/home_goods_creater.dart
  10. +8
    -4
      lib/widgets/home/home_goods/home_goods_header.dart
  11. +1
    -1
      lib/widgets/hot_ranking/hot_ranking_list/hot_ranking_bloc.dart

+ 27
- 27
example/android/app/build.gradle Visa fil

@@ -108,33 +108,33 @@ android {


// 应用信息配置
productFlavors {
// 智夜生活
zhiying {
applicationId "cn.zhios.zhiying"
versionCode 28
dimension "app"
versionName '1.2.28'
// 签名信息
signingConfig signingConfigs.zhiying
}
}
// 打包脚本
android.applicationVariants.all { variant ->
if (variant.buildType.name != "debug") {
variant.getPackageApplicationProvider().get().outputDirectory = new File(project.rootDir.absolutePath + "/app/build/outputs/apk")
}
variant.outputs.all { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
//这里修改apk文件名
def fileName = "${variant.productFlavors[0].name}_${releaseTime()}01_&V${variant.productFlavors[0].versionCode}.apk"
outputFileName = fileName
}
}
}
// productFlavors {
// // 智夜生活
// zhiying {
// applicationId "cn.zhios.zhiying"
// versionCode 28
// dimension "app"
// versionName '1.2.28'
// // 签名信息
// signingConfig signingConfigs.zhiying
// }
// }
//
// // 打包脚本
// android.applicationVariants.all { variant ->
// if (variant.buildType.name != "debug") {
// variant.getPackageApplicationProvider().get().outputDirectory = new File(project.rootDir.absolutePath + "/app/build/outputs/apk")
// }
//
// variant.outputs.all { output ->
// def outputFile = output.outputFile
// if (outputFile != null && outputFile.name.endsWith('.apk')) {
// //这里修改apk文件名
// def fileName = "${variant.productFlavors[0].name}_${releaseTime()}01_&V${variant.productFlavors[0].versionCode}.apk"
// outputFileName = fileName
// }
// }
// }

configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->


+ 6
- 3
lib/dialog/global_dialog/intellect_search_goods_dialog/intellect_create.dart Visa fil

@@ -115,14 +115,17 @@ class IntellectCreate {

///检查字段是否被监听
static void validate(BuildContext context, IntellectSearchSetModel setModel) async {
//获取粘贴板的文字
ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
String content = data?.text?.trim() ?? "";
//是否监听
if (setModel.isListen != "1") {

///粘贴版的文字如果是空直接跳出不检索
if (content == null || content.length == 0) {
return;
}

if (content == null || content.length == 0) {
//是否监听
if (setModel.isListen != "1") {
return;
}



+ 9
- 0
lib/pages/custom_page/bloc/background_bloc.dart Visa fil

@@ -0,0 +1,9 @@

import 'dart:async';

class BackgroundBloc{
StreamController streamController=StreamController.broadcast();

Stream get outData =>streamController.stream;

}

+ 15
- 4
lib/pages/custom_page/bloc/custom_page_repository.dart Visa fil

@@ -19,10 +19,21 @@ class CustomPageRepository {
var result = await NetUtil.post('/api/v1/mod/$skipIdentifier', method: NetMethod.GET, cache: true);
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
List mobList = List.from(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list']);
customPageData.modList=List();
if (!EmptyUtil.isEmpty(mobList)) {
customPageData.modList= mobList.map((e) => Map<String, dynamic>.from(e)).toList();
if(result.containsKey('out_data')){
customPageData.backgroundModel=BackgroundModel.fromJson(json.decode(result['out_data']));
for(var item in mobList){
customPageData.modList.add(Map<String, dynamic>.from(item));
}
if(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA].containsKey('out_data')&&result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['out_data']!=''){
try{
var jsonData=json.decode(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['out_data']);
print(jsonData);
customPageData.backgroundModel=BackgroundModel.fromJson(jsonData);
}catch(e,s){
print(e);
print(s);
}

}
return customPageData;
}
@@ -50,7 +61,7 @@ class CustomPageRepository {
for(var item in mobList){
customPageData.modList.add(Map<String, dynamic>.from(item));
}
if(result.containsKey('out_data')){
if(result.containsKey('out_data')&&result['out_data']!=''){
var jsonData=json.decode(result['out_data']);
print(jsonData);
customPageData.backgroundModel=BackgroundModel.fromJson(jsonData);


+ 20
- 14
lib/pages/custom_page/custom_item_page.dart Visa fil

@@ -13,7 +13,6 @@ import 'bloc/custom_item_page_state.dart';
import 'bloc/custom_item_page_event.dart';
import 'bloc/custom_item_page_repository.dart';


///
/// 通用模块的分类导航下的子模块
///
@@ -24,8 +23,9 @@ class CustomItemPage extends StatelessWidget {
final String modPid;
final String modId;
final bool needBuildStatus;
Function(double) scroller;

CustomItemPage(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus);
CustomItemPage(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus, {this.scroller});

@override
Widget build(BuildContext context) {
@@ -35,7 +35,7 @@ class CustomItemPage extends StatelessWidget {
],
child: BlocProvider<CustomItemPageBloc>(
create: (_) => CustomItemPageBloc(CustomItemPageRepository(this.data, this.tabIndex, this.modId, this.modPid)),
child: _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus),
child: _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus,scroller: this.scroller,),
),
);
}
@@ -47,8 +47,9 @@ class _CustomItemPageContainer extends StatefulWidget {
final String modPid;
final String modId;
final bool needBuildStatus;
final Function(double) scroller;

const _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus, {Key key}) : super(key: key);
const _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus, {this.scroller, Key key}) : super(key: key);

@override
__CustomItemPageContainerState createState() => __CustomItemPageContainerState();
@@ -62,7 +63,6 @@ class __CustomItemPageContainerState extends State<_CustomItemPageContainer> wit
RefreshController _refreshController;
final EventBus _eventBus = EventBus();


/// 回到顶点
void _scrollTop() {
// _controller.jumpTo(0);
@@ -90,7 +90,12 @@ class __CustomItemPageContainerState extends State<_CustomItemPageContainer> wit
void initState() {
_controller = ScrollController();
_refreshController = RefreshController(initialRefresh: false);
_initEvent();
_initEvent();_controller.addListener(() {
print(_controller.offset.toString());
if(widget.scroller!=null){
widget?.scroller(_controller.offset);
}
});
super.initState();
}

@@ -164,7 +169,10 @@ class __CustomItemPageContainerState extends State<_CustomItemPageContainer> wit
),
Align(
alignment: Alignment.bottomCenter,
child: Container( margin: const EdgeInsets.only(bottom: 8), child: _buildAuthWidget(model),), //_buildAuthWidget(model),
child: Container(
margin: const EdgeInsets.only(bottom: 8),
child: _buildAuthWidget(model),
), //_buildAuthWidget(model),
)
],
),
@@ -176,11 +184,11 @@ class __CustomItemPageContainerState extends State<_CustomItemPageContainer> wit
List<Widget> result = [];
for (int i = 0; i < datas.length; i++) {
WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
if(item.modName == 'audit_tip'){
if (item.modName == 'audit_tip') {
Logger.debug('授权组件,跳过');
continue;
}
if(item.modName == 'product'){
if (item.modName == 'product') {
datas[i]['eventBus'] = _eventBus;
}
result.addAll(WidgetFactory.create(
@@ -226,20 +234,18 @@ class __CustomItemPageContainerState extends State<_CustomItemPageContainer> wit
}

/// 特殊的授权组件
Widget _buildAuthWidget(final List<Map<String, dynamic>> datas){
Widget _buildAuthWidget(final List<Map<String, dynamic>> datas) {
int length = datas?.length ?? 0;
if(length == 0) return Container();
if (length == 0) return Container();
Widget rlt;
for (int i = 0; i < datas.length; i++) {
WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
if(item.modName == 'audit_tip'){
if (item.modName == 'audit_tip') {
rlt = HomeAuth(datas[i]);
break;
}
}

return rlt ?? Container();

}

}

+ 69
- 27
lib/pages/custom_page/custom_page.dart Visa fil

@@ -13,6 +13,7 @@ import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/background_bloc.dart';
import 'bloc/custom_page_bloc.dart';
import 'bloc/custom_page_state.dart';
import 'bloc/custom_page_event.dart';
@@ -35,7 +36,7 @@ class CustomPage extends StatefulWidget {
class _CustomPageState extends State<CustomPage> {
@override
Widget build(BuildContext context) {
Logger.log("数据: "+widget?.data.toString());
Logger.log("数据: " + widget?.data.toString());
return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: MainPageBgNotifier()),
@@ -67,14 +68,25 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single
// 是否有TabBar
bool _isHasTabBar = false;

double backgroundTopMargin = 0;

BackgroundBloc backgroundBloc;

/// 刷新
void _onRefreshEvent() async {
BlocProvider.of<CustomPageBloc>(context).add(CustomPageRefreshEvent());
}

@override
void initState() {
backgroundBloc=BackgroundBloc();
super.initState();
}

@override
void dispose() {
_tabController?.dispose();
backgroundBloc.streamController.close();
super.dispose();
}

@@ -102,7 +114,7 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single
/// 有数据
if (state is CustomPageLoadedState) {
if (EmptyUtil.isEmpty(state.model)) return _buildEmptyWidget();
return _buildMainWidget(state.model,state.backgroundModel);
return _buildMainWidget(state.model, state.backgroundModel);
}

/// 初始化失败
@@ -118,22 +130,21 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single
}

/// 有数据
Widget _buildMainWidget(List<Map<String, dynamic>> model,BackgroundModel backgroundModel) {
Widget _buildMainWidget(List<Map<String, dynamic>> model, BackgroundModel backgroundModel) {
return Scaffold(
appBar: _buildAppbar(model?.first),
backgroundColor: HexColor.fromHex(backgroundModel?.bgColor??""),
backgroundColor: HexColor.fromHex(backgroundModel?.bgColor == null || backgroundModel?.bgColor == '' ? "#FFF9F9F9" : backgroundModel?.bgColor ?? "#FFF9F9F9"),
// floatingActionButton: _buildFloatWidget(),
floatingActionButtonLocation: _CustomFloatingActionButtonLocation(FloatingActionButtonLocation.endFloat, 0, -100),
body: Stack(
children: <Widget>[
_buildBackground(backgroundModel),
Column(children: _buildFirstWidget(model)),
Column(children: _buildFirstWidget(model, backgroundModel)),
],
),
);
}


/// 骨架图
Widget _buildSkeletonWidget() {
return Scaffold();
@@ -190,7 +201,7 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single
}

/// 数据,生成第一层widget
List<Widget> _buildFirstWidget(List<Map<String, dynamic>> model) {
List<Widget> _buildFirstWidget(List<Map<String, dynamic>> model, BackgroundModel backgroundModel) {
List<Widget> result = [];

// 分类导航的key ⚠️ 这里先写成Test 后续要改
@@ -227,7 +238,7 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single

// 没有appbar并且没有tabbar,则给第一个元素加边距
if (!_isHasAppbar) {
result.insert(0, SizedBox(height: MediaQueryData.fromWindow(window).padding.top, child: Container(color: HexColor.fromHex(''),),));
result.insert(0, SizedBox(height: MediaQueryData.fromWindow(window).padding.top, child: Container(color: HexColor.fromHex(backgroundModel?.headerBg?.mainColor))));
}

return result;
@@ -285,7 +296,14 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single
// 1、导航栏没开启的情况 传null进去进行获取没开启导航栏的widget集合
if (EmptyUtil.isEmpty(listStyle)) {
result.add(Expanded(
child: CustomItemPage(null, 0, model['mod_id']?.toString() ?? null, model['mod_pid']?.toString() ?? null, (!_isHasAppbar && index == 0 )),
child: CustomItemPage(
null,
0,
model['mod_id']?.toString() ?? null,
model['mod_pid']?.toString() ?? null,
(!_isHasAppbar && index == 0),
scroller: _listenScroller,
),
));
return result;
}
@@ -306,11 +324,11 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single
isScrollable: /*listStyle.length <= 5 ? false : */ true,
labelColor: HexColor.fromHex(data['choose_text_color'] ?? '#FF4242'),
labelStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
unselectedLabelColor: HexColor.fromHex(data['text_color'] ?? '#999999'),
unselectedLabelColor: HexColor.fromHex(data['text_color'] ?? '#999999'),
unselectedLabelStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
indicatorSize: TabBarIndicatorSize.label,
indicator: MaterialIndicator(
color: HexColor.fromHex(data['choose_color'] ?? '#FF4242'),
color: HexColor.fromHex(data['choose_color'] ?? '#FF4242'),
bottomLeftRadius: 1.25,
topLeftRadius: 1.25,
topRightRadius: 1.25,
@@ -338,28 +356,42 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single
List<Widget> _buildTabBarViewChildren(final List<Map<String, dynamic>> listStyle, final String modId, final String modPid, final int index) {
List<Widget> result = [];
for (int i = 0; i < listStyle.length; i++) {
result.add(CustomItemPage(listStyle[i], i, modId, modPid, (!_isHasAppbar && !_isHasTabBar && index == 0 )));
result.add(CustomItemPage(
listStyle[i],
i,
modId,
modPid,
(!_isHasAppbar && !_isHasTabBar && index == 0),
scroller: _listenScroller,
));
}
return result;
}


_buildBackground(BackgroundModel backgroundModel) {
if (backgroundModel != null) {
var headerBg = backgroundModel.headerBg;
return Container(
height: double.tryParse(headerBg?.height)?? 0,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [HexColor.fromHex(headerBg?.mainColor ?? ""), HexColor.fromHex(headerBg?.assistColor ?? ""), HexColor.fromHex(headerBg?.minorColor ?? "")])),
);
}else{
return Container();
}
}
if (backgroundModel != null) {
var headerBg = backgroundModel.headerBg;
return StreamBuilder(
stream: backgroundBloc.outData,
builder: (context,asncy){
return Container(
constraints: BoxConstraints(minHeight: 0),
height: (double.tryParse(headerBg?.height)??0)+backgroundTopMargin ?? 0,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [HexColor.fromHex(headerBg?.mainColor ?? ""), HexColor.fromHex(headerBg?.assistColor ?? ""), HexColor.fromHex(headerBg?.minorColor ?? "")])),
);
},
);

} else {
return Container();
}
}

// /// 悬浮按钮
// Widget _buildFloatWidget() {
@@ -377,6 +409,16 @@ class __CommonPageContainerState extends State<_CommonPageContainer> with Single
// );
// }

///监听页面滚动
_listenScroller(double offset) {
print(offset.toString());
if (offset > 0) {
backgroundTopMargin = -offset;
if (backgroundTopMargin > -500) {
backgroundBloc.streamController.add("");
}
}
}
}

/// 回到顶部的icon


+ 14
- 14
lib/register.dart Visa fil

@@ -138,20 +138,20 @@ class BaseWidgetRegister {
MobPushUtil.setCanPush();
// 缓存可能用到的数据,预加载
Application.addMethod(() {
// 精选的数据
NetUtil.post('/api/v1/rec/featured?page=1', method: NetMethod.GET, cache: true, showToast: false);
// 淘宝的数据
NetUtil.post('/api/v1/rec/taobao?page=1', method: NetMethod.GET, cache: true, showToast: false);
// 京东
NetUtil.post('/api/v1/rec/jd?page=1', method: NetMethod.GET, cache: true, showToast: false);
// 唯品会
NetUtil.post('/api/v1/rec/vip?page=1', method: NetMethod.GET, cache: true, showToast: false);
// 拼多多
NetUtil.post('/api/v1/rec/pdd?page=1', method: NetMethod.GET, cache: true, showToast: false);
// 苏宁
NetUtil.post('/api/v1/rec/suning?page=1', method: NetMethod.GET, cache: true, showToast: false);
// 考拉
NetUtil.post('/api/v1/rec/kaola?page=1', method: NetMethod.GET, cache: true, showToast: false);
// // 精选的数据
// NetUtil.post('/api/v1/rec/featured?page=1', method: NetMethod.GET, cache: true, showToast: false);
// // 淘宝的数据
// NetUtil.post('/api/v1/rec/taobao?page=1', method: NetMethod.GET, cache: true, showToast: false);
// // 京东
// NetUtil.post('/api/v1/rec/jd?page=1', method: NetMethod.GET, cache: true, showToast: false);
// // 唯品会
// NetUtil.post('/api/v1/rec/vip?page=1', method: NetMethod.GET, cache: true, showToast: false);
// // 拼多多
// NetUtil.post('/api/v1/rec/pdd?page=1', method: NetMethod.GET, cache: true, showToast: false);
// // 苏宁
// NetUtil.post('/api/v1/rec/suning?page=1', method: NetMethod.GET, cache: true, showToast: false);
// // 考拉
// NetUtil.post('/api/v1/rec/kaola?page=1', method: NetMethod.GET, cache: true, showToast: false);
return null;
});



+ 2
- 0
lib/widgets/home/home_goods/bloc/home_goods_header_bloc.dart Visa fil

@@ -12,6 +12,8 @@ class HomeGoodsHeaderBloc extends BlocBase {

Stream<List<HomeGoodsHeaderModel>> get outData => _tabController.stream;

bool showHeader=true;

@override
void dispose() {
_tabController?.close();


+ 19
- 5
lib/widgets/home/home_goods/home_goods_creater.dart Visa fil

@@ -7,21 +7,35 @@ import 'package:zhiying_base_widget/widgets/home/home_goods/home_goods.dart';
import 'package:zhiying_base_widget/widgets/home/home_goods/home_goods_header.dart';
import 'package:zhiying_comm/util/base_bloc.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'dart:convert' as convert;

import 'models/home_goods_style_model.dart';

class GoodsListCreater extends WidgetCreater {
@override
List<Widget> createWidgets(Map<String, dynamic> model) {
print('创建商品列表');
// final EventBus _eventBus = EventBus();
String d = model['data'];
dynamic jsonData = convert.jsonDecode(d);
var _style = HomeGoodsStyleModel.fromJson(Map<String, dynamic>.from(jsonData));
final EventBus _eventBus = model['eventBus'];
Widget _widget = BlocProvider<HomeGoodsHeaderBloc>(bloc: HomeGoodsHeaderBloc(), child: HomeGoodsHeader(model, _eventBus));
Map<String, dynamic> json = jsonDecode(model['data']);

return [
SliverToBoxAdapter(child: Container(margin: EdgeInsets.only(top: ParseUtil.stringParseDouble(null != json ? json['top_margin'] : '0')))),
SliverPersistentHeader(pinned: true, floating: false, delegate: HomeGoodsHeaderDelegate(_widget)),
HomeGoods(model, eventBus: _eventBus),
];
List<Widget> listWidget = List();
listWidget.add(SliverToBoxAdapter(child: Container(margin: EdgeInsets.only(top: ParseUtil.stringParseDouble(null != json ? json['top_margin'] : '0')))));

double height = 64.0;

///是否添加头部
if (_style.recommendList.length < 2) {
height = 0;
}
listWidget.add(SliverPersistentHeader(pinned: true, floating: false, delegate: HomeGoodsHeaderDelegate(_widget, height: height)));

listWidget.add(HomeGoods(model, eventBus: _eventBus));
return listWidget;
}

@override


+ 8
- 4
lib/widgets/home/home_goods/home_goods_header.dart Visa fil

@@ -13,8 +13,8 @@ import 'package:zhiying_comm/zhiying_comm.dart';

class HomeGoodsHeaderDelegate extends SliverPersistentHeaderDelegate {
final Widget child;
HomeGoodsHeaderDelegate(this.child) : super();
final double height;
HomeGoodsHeaderDelegate(this.child,{this.height=64.0}) : super();

@override
Widget build(
@@ -24,10 +24,10 @@ class HomeGoodsHeaderDelegate extends SliverPersistentHeaderDelegate {
}

@override
double get maxExtent => 64.0;
double get maxExtent =>height;

@override
double get minExtent => 64.0;
double get minExtent => height;

@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) =>
@@ -71,8 +71,11 @@ class _HomeGoodsHeaderState extends State<_HomeGoodsHeader>
TabController _tabController;
int _currentIndex = 0;

HomeGoodsHeaderBloc _bloc;

@override
void initState() {
_bloc=BlocProvider.of<HomeGoodsHeaderBloc>(context);
String d = widget.model['data'];
dynamic json = convert.jsonDecode(d);
_style = HomeGoodsStyleModel.fromJson(Map<String, dynamic>.from(json));
@@ -91,6 +94,7 @@ class _HomeGoodsHeaderState extends State<_HomeGoodsHeader>
_widgets.clear();

if(_style.recommendList.length<2){
_bloc.showHeader=false;
return Container();
}



+ 1
- 1
lib/widgets/hot_ranking/hot_ranking_list/hot_ranking_bloc.dart Visa fil

@@ -38,7 +38,7 @@ class HotRankingListBloc extends BlocBase {
isLoading = true;
currentTypeId = typeId;
await NetUtil.request(
'/api/v1/rec/taobao?type_id=' + typeId + '&page=' + page.toString(),
'/api/v1/rec?pvd=taobao&category_id=' + typeId + '&page=' + page.toString(),
method: NetMethod.GET, onCache: (data) {
complete();
Loading.dismiss();


Laddar…
Avbryt
Spara