2021年1月22日金曜日

flutter with firebase

https://qiita.com/kimuradesu/items/b74c4908efb282d16a46 ::blazor with firebase

-------------------------------------------------------------------------------------------- 

://www.flutter-study.dev/ フラッターではじめるアプリ開発(ベータ版でWebもOK)

https://airhole.ymegane.org/flutter-for-web/  いまさらでもないが

ちなみに工学社の本は参考程度 上記のサイトのほうがまし

ツヤノの本は、firebase記事はないが、それ以外は充実 (とくにカメラ利用)

-------------------------------------------------------------------------------------------------------

いろいろあたってなんとか動いた記録

まず最新のflutter_core,cloud_firestoreをpub.get 

----------------------------------------------------------------      pubspec.yaml

name: my_flutter_app
description: A new Flutter application.

# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1

environment:
sdk: ">=2.7.0 <3.0.0"

dependencies:
flutter:
sdk: flutter


# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
firebase_core: "^0.7.0"
cloud_firestore: "^0.16.0"

dev_dependencies:
flutter_test:
sdk: flutter

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true

# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg

# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.

# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages

# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
------------------------------------------------------
android-package-name for firebase is com.example.my_flutter_app
(my_flutter_appというflutter project nameから導出される) 
できたjsonをmy_flutter_app/android/appに転送
firestoreにbooksというコレクションを作りauthor,titleの項目をつくり入れ込んでおく
----------------------------------------------------- main.dart
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyHomePage());
}

class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
var count = 1;

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Firestore Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Firestore Demo'),
),
body: createListView(),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Firestore 上にデータを追加
//
FirebaseFirestore.instance.collection('books').add({
'title': 'タイトル$count',
'author': '著者$count',
});
count += 1;
},
child: Icon(Icons.add),
),
),
);
}

createListView() {
FirebaseFirestore.instance.collection('books').snapshots().listen((data) {
print(data);
});

return StreamBuilder(
stream: FirebaseFirestore.instance.collection('books').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
// エラーの場合
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}

// 通信中の場合
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text('Loading ...');
default:
return ListView(
children: snapshot.data.docs.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document['title']),
subtitle: new Text(document['author']),
);
}).toList(),
);
}
},
);
}
}
----------------------------------------------------------navigation ex
import 'package:flutter/material.dart';

void main() =>
runApp(MaterialApp(
initialRoute: '/first',
routes: <String, WidgetBuilder> {
'/first':(BuildContext context) => FirstRoute(),
'/second': (BuildContext context) => SecondRoute(),
}
));

class FirstRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) => SecondRoute()
));
},
child: Text('push here',
style: TextStyle(fontSize: 20),
)),
],),),);
}
}

class SecondRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Route'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('push here',
style: TextStyle(fontSize: 20),
)),
],),),);
}
}

2021年1月8日金曜日

progressive-web-app and react-redux

https://eh-career.com/engineerhub/entry/2019/10/24/103000

PWAの作り方をサクッと学ぶ - 「ホーム画面に追加」「キャッシュ操作」「プッシュ通知」の実装

but -universal-project angular-pwa   not required

https://dev.classmethod.jp/articles/angular8-pwa/ :: ok

----------------------------------------------------------------------------------------------------------

index.js and app.js at tuyano textbook

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore} from 'redux';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';


// ステートの値
let state_value = {
counter:0,
message:"COUNTER"
}


// レデューサー
function counter(state = state_value, action) {
switch (action.type) {
case 'INCREMENT':
return {
counter:state.counter + 1,
message:"INCREMENT"
};
case 'DECREMENT':
return {
counter:state.counter - 1,
message:"DECREMENT"
};
default:
return state;
}
}


// ストアを作成
let store = createStore(counter);


// 表示をレンダリング
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);



import React, { Component } from 'react';
import { connect } from 'react-redux';
import './App.css';

// ステートのマッピング
//function mappingState(state) {
// return state;
//}
// Appコンポーネント
class App extends Component { // 3 lines belo are unnncessary
//constructor(props){
// super(props);
// }
render() {
return (
<div>
<h1>R edux example with 2 component :: Message and Button </h1>
<Message />
<Button />
</div>
);
}
}
// ストアのコネクト
//App = connect()(App); // unnecessary

// メッセージ表示のコンポーネント
class Message extends Component {
style = {
fontSize:"20pt",
padding:"20px 5px"
}
// this.props is store provided by Provider Tag in index.js
render(){
return (
<p style={this.style}>
{this.props.message}: {this.props.counter}
</p>
);
}
}
// ストアのコネクト
//Message = connect(mappingState)(Message);
Message = connect( (state) => state )(Message);

//
class Button extends Component {
style = {
fontSize:"16pt",
padding:"5px 10px"
}

constructor(){
super();
this.doAction = this.doAction.bind(this);
}

// ボタンクリックでディスパッチを実行
doAction(e){
if (e.shiftKey){
this.props.dispatch({ type:'DECREMENT' }); // passed to reducer named counter in index.js
} else {
this.props.dispatch({ type:'INCREMENT' });
}
}


render(){
return (
<button style={this.style}
onClick={this.doAction}>
click
</button>
);
}
}
// ストアのコネクト
Button = connect()(Button);

export default App;